Selaa lähdekoodia

nixos-modules: add nix-store USB backend

Load the store from an EXT2 file-system from USB storage.
remotes/server7/dabus
Emery Hemingway 9 kuukautta sitten
vanhempi
commit
99d43ceba1

+ 251
- 43
nixos-modules/genode-core.nix Näytä tiedosto

@@ -1,38 +1,70 @@
1 1
 { config, pkgs, lib, modulesPath, ... }:
2 2
 
3 3
 with lib;
4
-let localPackages = pkgs.buildPackages;
4
+let
5
+  localPackages = pkgs.buildPackages;
6
+  coreROMs = mkOption {
7
+    type = with types; listOf str;
8
+    default = [ ];
9
+    description = ''
10
+      List of label suffixes that when matched against
11
+      ROM requests shall be forwared to the core.
12
+    '';
13
+    example = [ "platform_info" ];
14
+  };
15
+  inputs = mkOption {
16
+    description = "List of packages to build a ROM store with.";
17
+    default = [ ];
18
+    type = types.listOf types.package;
19
+  };
5 20
 in {
6 21
   options.genode = {
22
+
7 23
     core = {
8 24
 
9 25
       prefix = mkOption {
10 26
         type = types.str;
11 27
         example = "hw-pc-";
28
+        description = "String prefix signifying the Genode core in use.";
12 29
       };
13 30
 
14 31
       supportedSystems = mkOption {
15 32
         type = types.listOf types.str;
16 33
         example = [ "i686-genode" "x86_64-genode" ];
34
+        description = "Hardware supported by this core.";
35
+      };
36
+
37
+      basePackages = mkOption {
38
+        type = types.listOf types.package;
39
+        description = ''
40
+          List of packages to make availabe before the Nix store is ready.
41
+          These are baked into <option>config.genode.core.image</option>.
42
+        '';
17 43
       };
18 44
 
19
-      basePackages = mkOption { type = types.listOf types.package; };
45
+      children = mkOption {
46
+        type = with types;
47
+          attrsOf (submodule {
48
+            options = {
49
+              inherit coreROMs inputs;
50
+              configFile = mkOption {
51
+                type = types.path;
52
+                description = ''
53
+                  Set of children at the lowest init level, these children must not
54
+                  have any dependency on a Nix store.
55
+                  Configuration format is a Dhall configuration of type
56
+                  <literal>Genode.Init.Child.Type</literal>.
57
+                  See https://git.sr.ht/~ehmry/dhall-genode/tree/master/Init/Child/Type
58
+                '';
59
+              };
60
+            };
61
+          });
62
+      };
20 63
 
21 64
     };
22 65
 
23 66
     boot = {
24 67
 
25
-      kernel = mkOption {
26
-        type = types.path;
27
-        default = "${pkgs.genodePackages.bender}/bender";
28
-      };
29
-
30
-      initrd = mkOption {
31
-        type = types.str;
32
-        default = "${pkgs.genodePackages.bender}/bender";
33
-        description = "Path to an image or a command-line arguments";
34
-      };
35
-
36 68
       configFile = mkOption {
37 69
         type = types.path;
38 70
         description = ''
@@ -49,9 +81,59 @@ in {
49 81
 
50 82
       romModules = mkOption {
51 83
         type = types.attrsOf types.path;
84
+        default = { };
52 85
         description = "Attr set of initial ROM modules";
53 86
       };
54 87
 
88
+      storeFsUuid = mkOption {
89
+        type = types.str;
90
+        default = import ./store-fs-uuid;
91
+        description = "Custom partition type of the nix-store file-system.";
92
+      };
93
+
94
+      storePartUuid = mkOption {
95
+        type = types.str;
96
+        default = import ./partition-type;
97
+        description = "Custom partition type of the nix-store file-system.";
98
+      };
99
+
100
+      storeBackend = mkOption {
101
+        type = types.enum [ "tarball" "usb" ]; # "parent"?
102
+        default = "tarball";
103
+        description = ''
104
+          Backend for the initial /nix/store file-system.
105
+
106
+          <variablelist>
107
+
108
+            <varlistentry>
109
+              <term><literal>tarball</literal></term>
110
+              <listitem>
111
+                <para>
112
+                  An in-memory tarball.
113
+                </para>
114
+              </listitem>
115
+            </varlistentry>
116
+
117
+            <varlistentry>
118
+              <term><literal>usb</literal></term>
119
+              <listitem>
120
+                <para>
121
+                  An EXT2 file-system backed by USB storage.
122
+                </para>
123
+              </listitem>
124
+            </varlistentry>
125
+
126
+          </variablelist>
127
+        '';
128
+      };
129
+
130
+      storePaths = mkOption {
131
+        type = with types; listOf package;
132
+        description = ''
133
+          Derivations to be included in the Nix store in the generated boot image.
134
+        '';
135
+      };
136
+
55 137
     };
56 138
 
57 139
   };
@@ -75,20 +157,17 @@ in {
75 157
       };
76 158
 
77 159
     mergeManifests = inputs:
78
-      localPackages.writeTextFile {
79
-        name = "manifest.dhall";
80
-        text = with builtins;
81
-          let
82
-            f = head: input:
83
-              if hasAttr "manifest" input then
84
-                ''
85
-                  ${head}, { mapKey = "${
86
-                    lib.getName input
87
-                  }", mapValue = ${input.manifest} }''
88
-              else
89
-                abort "${input.pname} does not have a manifest";
90
-          in (foldl' f "[" inputs) + "]";
91
-      };
160
+      with builtins;
161
+      let
162
+        f = head: input:
163
+          if hasAttr "manifest" input then
164
+            ''
165
+              ${head}, { mapKey = "${
166
+                lib.getName input
167
+              }", mapValue = ${input.manifest} }''
168
+          else
169
+            abort "${input.pname} does not have a manifest";
170
+      in (foldl' f "[" inputs) + "]";
92 171
 
93 172
     romDirectories = filterAttrs (_: value: value != null) (mapAttrs
94 173
       (name: value:
@@ -108,18 +187,113 @@ in {
108 187
       message = "invalid Genode core for this system";
109 188
     }];
110 189
 
190
+    genode.core.basePackages =
191
+      lib.optional (config.genode.boot.storeBackend == "usb")
192
+      pkgs.genodePackages.part_block;
193
+
194
+    genode.core.children =
195
+      # Component to steer the store_fs to a specific partition
196
+      (if config.genode.boot.storeBackend == "usb" then {
197
+        part_block.configFile = builtins.toFile "part_block.dhall" ''
198
+          let Genode = env:DHALL_GENODE
199
+
200
+          let Init = Genode.Init
201
+
202
+          in  Init.Child.flat
203
+                Init.Child.Attributes::{
204
+                , binary = "part_block"
205
+                , resources = Init.Resources::{ ram = Genode.units.MiB 8 }
206
+                , config = Init.Config::{
207
+                  , attributes = toMap { ignore_mbr = "yes" }
208
+                  , policies =
209
+                    [ Init.Config.Policy::{
210
+                      , service = "Block"
211
+                      , label = Init.LabelSelector.prefix "store_fs"
212
+                      , attributes = toMap
213
+                          { partition = "1"
214
+                          , writeable = "yes"
215
+                          , TODO = "select by partition UUID"
216
+                          }
217
+                      }
218
+                    ]
219
+                  }
220
+                }
221
+        '';
222
+      } else
223
+        { }) // {
224
+          store_fs.configFile = let
225
+
226
+            storeVfsConfig = {
227
+              tarball = ''
228
+                VFS.vfs [ VFS.leafAttrs "tar" (toMap { name = "${config.system.build.tarball.fileName}.tar" }) ]
229
+              '';
230
+              usb = ''
231
+                VFS.vfs [ VFS.leafAttrs "rump" (toMap { fs = "ext2fs", ram="12M" }) ]
232
+              '';
233
+            }.${config.genode.boot.storeBackend};
234
+
235
+            storeResources = {
236
+              tarball = "Init.Resources.default";
237
+              usb = "Init.Resources::{ caps = 256, ram = Genode.units.MiB 16 }";
238
+            }.${config.genode.boot.storeBackend};
239
+
240
+          in builtins.toFile "store_fs.dhall" ''
241
+            let Genode = env:DHALL_GENODE
242
+
243
+            let Init = Genode.Init
244
+
245
+            let VFS = Genode.VFS
246
+
247
+            in  Init.Child.flat
248
+                  Init.Child.Attributes::{
249
+                  , binary = "vfs"
250
+                  , resources = ${storeResources}
251
+                  , config = Init.Config::{
252
+                    , content = [ ${storeVfsConfig} ]
253
+                    , policies =
254
+                      [ Init.Config.Policy::{
255
+                        , service = "File_system"
256
+                        , label = Init.LabelSelector.suffix "nix-store"
257
+                        , attributes = toMap { root = "/nix/store" }
258
+                        }
259
+                      , Init.Config.Policy::{
260
+                        , service = "File_system"
261
+                        , label = Init.LabelSelector.prefix "store_rom"
262
+                        , attributes = toMap { root = "/" }
263
+                        }
264
+                      ]
265
+                    }
266
+                  }
267
+          '';
268
+        };
269
+
111 270
     genode.boot.configFile = let
112 271
       tarball =
113 272
         "${config.system.build.tarball}/tarball/${config.system.build.tarball.fileName}.tar";
114
-      manifest = mergeManifests (map addManifest
115
-        (config.genode.core.basePackages ++ [ config.system.build.tarball ]
116
-          ++ (with pkgs.genodePackages; [
117
-            init
118
-            cached_fs_rom
119
-            jitter_sponge
120
-            report_rom
121
-            vfs
122
-          ])));
273
+
274
+      storeBackendInputs = {
275
+        tarball = [ config.system.build.tarball ];
276
+        usb = [ pkgs.genodePackages.rump ];
277
+      }.${config.genode.boot.storeBackend};
278
+
279
+      coreInputs = with builtins;
280
+        concatMap (getAttr "inputs") (attrValues config.genode.core.children);
281
+
282
+      manifest =
283
+        # Manifests are Dhall metadata to be attached to every
284
+        # package to be used for dynamically buildings enviroments
285
+        # using Dhall expressions. Probably not worth pursuing.
286
+        pkgs.writeText "manifest.dhall" (mergeManifests (map addManifest
287
+          (with pkgs.genodePackages;
288
+            config.genode.core.basePackages ++ storeBackendInputs
289
+            ++ [ init cached_fs_rom jitter_sponge report_rom vfs ]
290
+            ++ coreInputs))
291
+          + lib.optionalString (config.genode.boot.romModules != { }) ''
292
+            # [ { mapKey = "romModules", mapValue = [ ${
293
+              toString (mapAttrsToList
294
+                (k: v: '', { mapKey = "${k}", mapValue = "${v}" }'')
295
+                config.genode.boot.romModules)
296
+            }] } ]'');
123 297
 
124 298
       storeRomPolicies = mapAttrsToList
125 299
         (name: value: '', { mapKey = "${name}", mapValue = "${value}" }'')
@@ -134,23 +308,38 @@ in {
134 308
                   Genode.Init.LabelSelector.Type.Partial
135 309
                     { prefix = Some "nixos -> ${name}", suffix = Some "${suffix}" }
136 310
               }
137
-            , route = Genode.Init.Route.parent (Some "${suffix}")
311
+            , route = Genode.Init.Route.parentLabel "${suffix}"
138 312
             }
139 313
           '') value.coreROMs) config.genode.init.children));
140 314
 
315
+      extraCoreChildren = "[ ${
316
+          toString (lib.mapAttrsToList (name: value:
317
+            '', { mapKey = "${name}", mapValue = ${value.configFile} }'')
318
+            config.genode.core.children)
319
+        } ]";
320
+
141 321
     in localPackages.runCommand "boot.dhall" { } ''
142 322
       cat > $out << EOF
143 323
       let Genode = env:DHALL_GENODE in
324
+      let VFS = Genode.VFS
325
+      let XML = Genode.Prelude.XML
326
+      in
144 327
       ${./store-wrapper.dhall}
145
-      (${config.genode.init.configFile})
146
-      "${config.system.build.tarball.fileName}.tar"
147
-      $(stat --format '%s' ${tarball})
148
-      ([${toString storeRomPolicies} ] : Genode.Prelude.Map.Type Text Text)
149
-      ([${extraRoutes} ] : List Genode.Init.ServiceRoute.Type)
150
-      ${manifest}
328
+      { extraCoreChildren = ${extraCoreChildren}
329
+      , subinit = ${config.genode.init.configFile}
330
+      , storeSize = $(stat --format '%s' ${tarball})
331
+      , storeRomPolicies = [${
332
+        toString storeRomPolicies
333
+      } ] : Genode.Prelude.Map.Type Text Text
334
+      , routes = [${extraRoutes} ] : List Genode.Init.ServiceRoute.Type
335
+      , bootManifest = ${manifest}
336
+      }
151 337
       EOF
152 338
     '';
153 339
 
340
+    genode.boot.storePaths = with builtins;
341
+      [ config.genode.init.configFile ] ++ (attrValues romDirectories);
342
+
154 343
     # Create the tarball of the store to live in core ROM
155 344
     system.build.tarball =
156 345
       pkgs.callPackage "${modulesPath}/../lib/make-system-tarball.nix" {
@@ -181,6 +370,25 @@ in {
181 370
       xmllint --noout $out
182 371
     '';
183 372
 
373
+    system.build.bootDriveImage = let
374
+      espImage = import ./lib/make-esp-fs.nix { inherit config pkgs; };
375
+      storeFsImage =
376
+        pkgs.callPackage ./lib/make-ext2-fs.nix { inherit config pkgs; };
377
+      bootDriveImage = import ./lib/make-bootable-image.nix {
378
+        inherit config pkgs espImage storeFsImage;
379
+      };
380
+    in bootDriveImage;
381
+
382
+    # virtualisation.useEFIBoot = config.genode.boot.storeBackend == "usb";
383
+
384
+    virtualisation.qemu.options =
385
+      lib.optionals (config.genode.boot.storeBackend == "usb") [
386
+        "-bios ${pkgs.buildPackages.OVMF.fd}/FV/OVMF.fd"
387
+        "-drive id=usbdisk,file=${config.system.build.bootDriveImage},if=none,readonly"
388
+        "-usb"
389
+        "-device usb-storage,drive=usbdisk"
390
+      ];
391
+
184 392
   };
185 393
 
186 394
 }

+ 81
- 9
nixos-modules/hardware.nix Näytä tiedosto

@@ -30,6 +30,11 @@ with lib;
30 30
       '';
31 31
     };
32 32
 
33
+    hardware.usb.genode.enable = lib.mkEnableOption "USB driver";
34
+
35
+    hardware.usb.genode.storage.enable =
36
+      lib.mkEnableOption "USB mass storage driver";
37
+
33 38
   };
34 39
 
35 40
   config = {
@@ -47,13 +52,18 @@ with lib;
47 52
       in lib.mapAttrsToList addrCheck config.networking.interfaces
48 53
       ++ lib.mapAttrsToList routeCheck config.networking.interfaces;
49 54
 
55
+    hardware.usb.genode.storage.enable = config.genode.boot.storeBackend
56
+      == "usb";
57
+
58
+    hardware.usb.genode.enable = config.hardware.usb.genode.storage.enable;
59
+
50 60
     hardware.genode.platform.policies = lib.lists.imap0 (i: name:
51 61
       builtins.toFile (name + ".platform-policy.dhall") ''
52 62
         let Genode = env:DHALL_GENODE
53 63
 
54 64
         in  Genode.Init.Config.Policy::{
55 65
             , service = "Platform"
56
-            , label = Genode.Init.LabelSelector.prefix "${name}.driver"
66
+            , label = Genode.Init.LabelSelector.prefix "nixos -> ${name}.driver"
57 67
             , content =
58 68
               [ Genode.Prelude.XML.leaf
59 69
                   { name = "pci"
@@ -64,12 +74,25 @@ with lib;
64 74
                   }
65 75
               ]
66 76
             }
67
-      '') (builtins.attrNames config.networking.interfaces);
77
+      '') (builtins.attrNames config.networking.interfaces)
78
+      ++ lib.optional config.hardware.usb.genode.enable
79
+      (builtins.toFile ("usb.platform-policy.dhall") ''
80
+        let Genode = env:DHALL_GENODE
81
+
82
+        in  Genode.Init.Config.Policy::{
83
+            , service = "Platform"
84
+            , label = Genode.Init.LabelSelector.prefix "usb_drv"
85
+            , content =
86
+              [ Genode.Prelude.XML.leaf
87
+                  { name = "pci", attributes = toMap { class = "USB" } }
88
+              ]
89
+            }
90
+      '');
68 91
 
69
-    genode.core.basePackages = with pkgs.genodePackages; [
70
-      acpi_drv
71
-      platform_drv
72
-    ];
92
+    genode.core.basePackages = with pkgs.genodePackages;
93
+      [ acpi_drv platform_drv ]
94
+      ++ lib.optional config.hardware.usb.genode.enable
95
+      pkgs.genodePackages.usb_drv;
73 96
 
74 97
     genode.init.children = let
75 98
 
@@ -108,7 +131,10 @@ with lib;
108 131
                       , caps = 128
109 132
                       , ram = Genode.units.MiB 4
110 133
                       }
111
-                    , routes = [ Init.ServiceRoute.parent "IO_MEM" ]
134
+                    , routes = [
135
+                      , Init.ServiceRoute.parent "IO_MEM"
136
+                      , Init.ServiceRoute.parent "Platform"
137
+                      ]
112 138
                     , config = Init.Config::{
113 139
                       , attributes = toMap { verbose = "true" }
114 140
                       , policies = ${policies}
@@ -199,7 +225,9 @@ with lib;
199 225
           };
200 226
         }) config.networking.interfaces;
201 227
 
202
-    in nics // (lib.filterAttrs (n: v: v != null) sockets) // {
228
+    in lib.filterAttrs (n: v: v != null) (nics // sockets);
229
+
230
+    genode.core.children = {
203 231
 
204 232
       acpi_drv = {
205 233
         coreROMs = [ "acpi_drv" ];
@@ -259,8 +287,52 @@ with lib;
259 287
                 }
260 288
         '';
261 289
       };
290
+    } // (if config.hardware.usb.genode.enable then {
262 291
 
263
-    };
292
+      usb_drv = {
293
+        coreROMs = [ "usb_drv" ];
294
+        configFile = builtins.toFile "usb_drv.dhall" ''
295
+          let Genode = env:DHALL_GENODE
296
+
297
+          let XML = Genode.Prelude.XML
298
+
299
+          let Init = Genode.Init
300
+
301
+          let storageEnable = ${
302
+            if config.hardware.usb.genode.storage.enable then
303
+              "True"
304
+            else
305
+              "False"
306
+          }
307
+
308
+          in  Init.Child.flat
309
+                Init.Child.Attributes::{
310
+                , binary = "usb_drv"
311
+                , provides = [ "Block", "Usb" ]
312
+                , resources = Init.Resources::{ caps = 256, ram = Genode.units.MiB 12 }
313
+                , routes = [ Init.ServiceRoute.parent "IO_MEM" ]
314
+                , config = Init.Config::{
315
+                  , attributes = toMap { uhci = "yes", ehci = "yes", xhci = "yes" }
316
+                  , content =
317
+                      if    storageEnable
318
+                      then  [ XML.leaf
319
+                                { name = "storage", attributes = XML.emptyAttributes }
320
+                            ]
321
+                      else  [] : List XML.Type
322
+                  , policies =
323
+                      if    storageEnable
324
+                      then  [ Init.Config.Policy::{
325
+                              , service = "Block"
326
+                              , label = Init.LabelSelector.prefix "store_fs"
327
+                              }
328
+                            ]
329
+                      else  [] : List Init.Config.Policy.Type
330
+                  }
331
+                }
332
+        '';
333
+      };
334
+    } else
335
+      { });
264 336
 
265 337
   };
266 338
 

+ 69
- 0
nixos-modules/lib/make-bootable-image.nix Näytä tiedosto

@@ -0,0 +1,69 @@
1
+# Builds a compressed EFI System Partition image
2
+{ config, pkgs, espImage, storeFsImage }:
3
+
4
+pkgs.stdenv.mkDerivation {
5
+  name = "boot.qcow2";
6
+
7
+  nativeBuildInputs = with pkgs.buildPackages; [
8
+    config.system.build.qemu
9
+    utillinux
10
+    zstd
11
+  ];
12
+
13
+  buildCommand = ''
14
+    img=./temp.raw
15
+    blockSize=512
16
+    sectorSize=$(( $blockSize * 1 ))
17
+    imgBytes=0
18
+
19
+    espSectorOffset=2048
20
+    esbByteOffset=$(( $espSectorOffset * $sectorSize ))
21
+
22
+    # Pad the front of the image
23
+    echo "Pad front of image with " $esbByteOffset " bytes"
24
+    truncate --size=$esbByteOffset $img
25
+
26
+    # Concatentenate the ESP
27
+    echo "Concatenate ESP ${espImage}"
28
+    zstdcat ${espImage} >> $img
29
+
30
+    imgBytes=$(stat --format=%s $img)
31
+    echo "Image is $(( $imgBytes >> 20 )) MiB with ESP partition"
32
+
33
+    nixSectorOffset=$(( ($imgBytes + $sectorSize - 1) / $sectorSize ))
34
+    nixByteOffset=$(( $nixSectorOffset * $sectorSize ))
35
+
36
+    # Pad the ESP
37
+    echo "Pad end of ESP with " $(( $nixByteOffset - $imgBytes )) " bytes"
38
+    truncate --size=$nixByteOffset $img
39
+
40
+    # Concatenate the nix partition
41
+    echo "Concatenate store ${storeFsImage}"
42
+    zstdcat ${storeFsImage} >> $img
43
+
44
+    imgBytes=$(stat --format=%s $img)
45
+    echo "Image is $(( $imgBytes >> 20 )) MiB with store partition"
46
+
47
+    endSectorOffset=$(( ($(stat --format=%s $img) + $sectorSize + 1) / $sectorSize ))
48
+    endByteOffset=$(( $endSectorOffset * $sectorSize ))
49
+
50
+    # Pad the end of the image
51
+    echo "Pad end of store with $(( $endByteOffset - $imgBytes )) bytes"
52
+    truncate --size=$endByteOffset $img
53
+
54
+    imgBytes=$(stat --format=%s $img)
55
+    echo "Image is $(( $imgBytes >> 20 )) MiB with final padding"
56
+
57
+    efiUuid=C12A7328-F81F-11D2-BA4B-00A0C93EC93B
58
+
59
+    # Create the partition table
60
+    sfdisk $img <<EOF
61
+      label: gpt
62
+      label-id: 44444444-4444-4444-8888-888888888888
63
+      start=$nixSectorOffset, type=${config.genode.boot.storePartUuid}
64
+      start=$espSectorOffset, type=$efiUuid
65
+    EOF
66
+
67
+    qemu-img convert $img $out
68
+  '';
69
+}

+ 72
- 0
nixos-modules/lib/make-esp-fs.nix Näytä tiedosto

@@ -0,0 +1,72 @@
1
+# Builds a compressed EFI System Partition image
2
+{ config, pkgs }:
3
+
4
+let
5
+  grub' = pkgs.buildPackages.grub2_efi;
6
+
7
+  # Name used by UEFI for architectures.
8
+  targetArch = if pkgs.stdenv.isi686 || config.boot.loader.grub.forcei686 then
9
+    "ia32"
10
+  else if pkgs.stdenv.isx86_64 then
11
+    "x64"
12
+  else if pkgs.stdenv.isAarch64 then
13
+    "aa64"
14
+  else
15
+    throw "Unsupported architecture";
16
+
17
+in pkgs.stdenv.mkDerivation {
18
+  name = "esp.img.zst";
19
+
20
+  nativeBuildInputs = with pkgs.buildPackages; [ grub' dosfstools mtools zstd ];
21
+
22
+  MODULES = [
23
+    "configfile"
24
+    "efi_gop"
25
+    "efi_uga"
26
+    "ext2"
27
+    "gzio"
28
+    "multiboot"
29
+    "multiboot2"
30
+    "normal"
31
+    "part_gpt"
32
+    "search_fs_uuid"
33
+  ];
34
+
35
+  buildCommand = ''
36
+    img=tmp.raw
37
+    bootdir=EFI/boot/
38
+    mkdir -p $bootdir
39
+
40
+    cat <<EOF > embedded.cfg
41
+    insmod configfile
42
+    insmod efi_gop
43
+    insmod efi_uga
44
+    insmod ext2
45
+    insmod normal
46
+    insmod part_gpt
47
+    insmod search_fs_uuid
48
+    search.fs_uuid ${config.genode.boot.storeFsUuid} root
49
+    set prefix=($root)/boot/grub
50
+    configfile /boot/grub/grub.cfg
51
+    EOF
52
+
53
+    grub-script-check embedded.cfg
54
+
55
+    ${grub'}/bin/grub-mkimage \
56
+      --config=embedded.cfg \
57
+      --output=$bootdir/boot${targetArch}.efi \
58
+      --prefix=/boot/grub \
59
+      --format=${grub'.grubTarget} \
60
+      $MODULES
61
+
62
+    # Make the ESP image twice as large as necessary
63
+    imageBytes=$(du --summarize --block-size=4096 --total $bootdir | tail -1 | awk '{ print int($1 * 8192) }')
64
+
65
+    truncate --size=$imageBytes $img
66
+    mkfs.vfat -n EFIBOOT --invariant $img
67
+    mcopy -sv -i $img EFI ::
68
+    fsck.vfat -nv $img
69
+
70
+    zstd --verbose --no-progress ./$img -o $out
71
+  '';
72
+}

+ 77
- 0
nixos-modules/lib/make-ext2-fs.nix Näytä tiedosto

@@ -0,0 +1,77 @@
1
+{ config, pkgs }:
2
+
3
+let
4
+  grub' = pkgs.buildPackages.grub2_efi;
5
+  sdClosureInfo = pkgs.buildPackages.closureInfo {
6
+    rootPaths = config.genode.boot.storePaths;
7
+  };
8
+in pkgs.stdenv.mkDerivation {
9
+  name = "ext2-fs.img.zstd";
10
+
11
+  nativeBuildInputs = with pkgs.buildPackages; [
12
+    e2fsprogs.bin
13
+    grub'
14
+    libfaketime
15
+    perl
16
+    fakeroot
17
+    zstd
18
+  ];
19
+
20
+  buildCommand = ''
21
+    img=temp.raw
22
+
23
+    # Create nix/store before copying path
24
+    mkdir -p ./rootImage/boot/grub ./rootImage/nix/store
25
+
26
+    cat <<EOF > ./rootImage/boot/grub/grub.cfg
27
+    set timeout=3
28
+    set default=0
29
+    set gfxpayload=auto
30
+
31
+    ${config.boot.loader.grub.extraEntries}
32
+    EOF
33
+
34
+    grub-script-check ./rootImage/boot/grub/grub.cfg
35
+
36
+    xargs -I % cp -a --reflink=auto % -t ./rootImage/nix/store/ < ${sdClosureInfo}/store-paths
37
+    (
38
+      GLOBIGNORE=".:.."
39
+      shopt -u dotglob
40
+
41
+      for f in ./files/*; do
42
+          cp -a --reflink=auto -t ./rootImage/ "$f"
43
+      done
44
+    )
45
+
46
+    # Also include a manifest of the closures in a format suitable for nix-store --load-db
47
+    cp ${sdClosureInfo}/registration ./rootImage/nix-path-registration
48
+
49
+    # Make a crude approximation of the size of the target image.
50
+    # If the script starts failing, increase the fudge factors here.
51
+    numInodes=$(find ./rootImage | wc -l)
52
+    numDataBlocks=$(du -s -c -B 4096 --apparent-size ./rootImage | tail -1 | awk '{ print int($1 * 1.10) }')
53
+    bytes=$((2 * 4096 * $numInodes + 4096 * $numDataBlocks))
54
+    echo "Creating an EXT2 image of $bytes bytes (numInodes=$numInodes, numDataBlocks=$numDataBlocks)"
55
+
56
+    truncate --size=$bytes $img
57
+
58
+    faketime -f "1970-01-01 00:00:01" fakeroot mkfs.ext2 -L NIXOS_GENODE -U ${config.genode.boot.storeFsUuid} -d ./rootImage $img
59
+
60
+    export EXT2FS_NO_MTAB_OK=yes
61
+    # I have ended up with corrupted images sometimes, I suspect that happens when the build machine's disk gets full during the build.
62
+    if ! fsck.ext2 -n -f $img; then
63
+      echo "--- Fsck failed for EXT2 image of $bytes bytes (numInodes=$numInodes, numDataBlocks=$numDataBlocks) ---"
64
+      cat errorlog
65
+      return 1
66
+    fi
67
+
68
+    echo "Resizing to minimum allowed size"
69
+    resize2fs -M $img
70
+
71
+    # And a final fsck, because of the previous truncating.
72
+    fsck.ext2 -n -f $img
73
+
74
+    # Compress to store
75
+    zstd --verbose --no-progress ./$img -o $out
76
+  '';
77
+}

+ 30
- 5
nixos-modules/nova.nix Näytä tiedosto

@@ -7,6 +7,17 @@ let
7 7
     inherit (config.nixpkgs) system localSystem crossSystem;
8 8
     inherit pkgs;
9 9
   };
10
+
11
+  bootDir = pkgs.runCommand "${config.system.name}-bootdir" { } ''
12
+    mkdir $out
13
+    gz() {
14
+      gzip --keep --to-stdout "$1" > "$2"
15
+    }
16
+    gz ${pkgs.genodePackages.genodeSources}/tool/boot/bender $out/bender.gz
17
+    gz ${pkgs.genodePackages.NOVA}/hypervisor-x86_64 $out/hypervisor.gz
18
+    gz ${config.genode.boot.image}/image.elf $out/image.elf.gz
19
+  '';
20
+
10 21
 in {
11 22
   genode.core = {
12 23
     prefix = "nova-";
@@ -15,13 +26,27 @@ in {
15 26
   };
16 27
 
17 28
   genode.boot = {
18
-
19
-    initrd =
20
-      "'${pkgs.genodePackages.NOVA}/hypervisor-x86_64 arg=iommu novpid serial,${config.genode.boot.image}/image.elf'";
21
-
22 29
     image =
23 30
       utils.novaImage config.system.name { } config.genode.boot.configFile;
24
-
25 31
   };
26 32
 
33
+  genode.boot.storePaths =
34
+    lib.optional (config.genode.boot.storeBackend == "usb") bootDir;
35
+
36
+  virtualisation.qemu.options =
37
+    lib.optionals (!config.virtualisation.useBootLoader) [
38
+      "-kernel '${pkgs.genodePackages.bender}/share/bender/bender'"
39
+      "-initrd '${pkgs.genodePackages.NOVA}/hypervisor-x86_64 arg=iommu logmem novpid serial,${config.genode.boot.image}/image.elf'"
40
+    ];
41
+
42
+  boot.loader.grub.extraEntries = ''
43
+    menuentry 'Genode on NOVA' {
44
+      insmod multiboot2
45
+      insmod gzio
46
+      multiboot2 ${bootDir}/bender.gz serial_fallback
47
+      module2 ${bootDir}/hypervisor.gz hypervisor iommu logmem novga novpid serial
48
+      module2 ${bootDir}/image.elf.gz image.elf
49
+    }
50
+  '';
51
+
27 52
 }

+ 1
- 0
nixos-modules/partition-type Näytä tiedosto

@@ -0,0 +1 @@
1
+"24b69406-18a1-428d-908e-d21a1437122c"

+ 2
- 6
nixos-modules/qemu-vm.nix Näytä tiedosto

@@ -83,9 +83,9 @@ let
83 83
     imap1 (idx: drive: drive // { device = driveDeviceName idx; });
84 84
 
85 85
   efiPrefix = if (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) then
86
-    "${pkgs.OVMF.fd}/FV/OVMF"
86
+    "${pkgs.buildPackages.OVMF.fd}/FV/OVMF"
87 87
   else if pkgs.stdenv.isAarch64 then
88
-    "${pkgs.OVMF.fd}/FV/AAVMF"
88
+    "${pkgs.buildPackages.OVMF.fd}/FV/AAVMF"
89 89
   else
90 90
     throw "No EFI firmware available for platform";
91 91
   efiFirmware = "${efiPrefix}_CODE.fd";
@@ -516,10 +516,6 @@ in {
516 516
         "-device usb-kbd"
517 517
         "-device usb-tablet"
518 518
       ])
519
-      (mkIf (!cfg.useBootLoader) [
520
-        "-kernel ${config.genode.boot.kernel}"
521
-        "-initrd ${config.genode.boot.initrd}"
522
-      ])
523 519
       (mkIf cfg.useEFIBoot [
524 520
         "-drive if=pflash,format=raw,unit=0,readonly,file=${efiFirmware}"
525 521
         "-drive if=pflash,format=raw,unit=1,file=$NIX_EFI_VARS"

+ 1
- 0
nixos-modules/store-fs-uuid Näytä tiedosto

@@ -0,0 +1 @@
1
+"9668f8dd-d9a0-4398-a55a-0d499d5e5cbb"

+ 155
- 166
nixos-modules/store-wrapper.dhall Näytä tiedosto

@@ -2,195 +2,184 @@ let Genode = env:DHALL_GENODE
2 2
 
3 3
 let Prelude = Genode.Prelude
4 4
 
5
+let XML = Prelude.XML
6
+
5 7
 let Init = Genode.Init
6 8
 
7 9
 let Child = Init.Child
8 10
 
9 11
 let TextMapType = Prelude.Map.Type Text
10 12
 
13
+let ChildMapType = TextMapType Child.Type
14
+
11 15
 let Manifest/Type = TextMapType (TextMapType Text)
12 16
 
13
-in  λ(subinit : Init.Type) →
14
-    λ(storeName : Text) →
15
-    λ(storeSize : Natural) →
16
-    λ(storeRomPolicies : Prelude.Map.Type Text Text) →
17
-    λ(routes : List Init.ServiceRoute.Type) →
18
-    λ(bootManifest : Manifest/Type) →
17
+in  λ ( params
18
+      : { extraCoreChildren : ChildMapType
19
+        , subinit : Init.Type
20
+        , storeSize : Natural
21
+        , storeRomPolicies : Prelude.Map.Type Text Text
22
+        , routes : List Init.ServiceRoute.Type
23
+        , bootManifest : Manifest/Type
24
+        }
25
+      ) →
19 26
       Genode.Boot::{
20 27
       , config = Init::{
21
-        , routes
28
+        , routes = params.routes
22 29
         , children =
23 30
             let child = Prelude.Map.keyValue Child.Type
24 31
 
25
-            in  [ child
26
-                    "timer"
27
-                    ( Child.flat
28
-                        Child.Attributes::{
29
-                        , binary = "timer_drv"
30
-                        , provides = [ "Timer" ]
31
-                        }
32
-                    )
33
-                , child
34
-                    "rtc"
35
-                    ( Child.flat
36
-                        Child.Attributes::{
37
-                        , binary = "rtc_drv"
38
-                        , provides = [ "Rtc" ]
39
-                        , routes = [ Init.ServiceRoute.parent "IO_PORT" ]
40
-                        }
41
-                    )
42
-                , child
43
-                    "jitter_sponge"
44
-                    ( Child.flat
45
-                        Child.Attributes::{
46
-                        , binary = "jitter_sponge"
47
-                        , provides = [ "Terminal" ]
48
-                        , config = Init.Config::{
49
-                          , policies =
50
-                            [ Init.Config.Policy::{
51
-                              , service = "Terminal"
52
-                              , label = Init.LabelSelector.suffix "entropy"
53
-                              }
54
-                            ]
32
+            in    [ child
33
+                      "timer"
34
+                      ( Child.flat
35
+                          Child.Attributes::{
36
+                          , binary = "timer_drv"
37
+                          , provides = [ "Timer" ]
38
+                          , config = Init.Config::{
39
+                            , policies =
40
+                              [ Init.Config.Policy::{
41
+                                , service = "Timer"
42
+                                , label = Init.LabelSelector.none
43
+                                }
44
+                              ]
45
+                            }
55 46
                           }
56
-                        }
57
-                    )
58
-                , child
59
-                    "store_fs"
60
-                    ( Child.flat
61
-                        Child.Attributes::{
62
-                        , binary = "vfs"
63
-                        , config = Init.Config::{
64
-                          , content =
65
-                              let VFS = Genode.VFS
66
-
67
-                              in  [ VFS.vfs
68
-                                      [ VFS.leafAttrs
69
-                                          "tar"
70
-                                          (toMap { name = storeName })
71
-                                      ]
72
-                                  ]
73
-                          , policies =
74
-                            [ Init.Config.Policy::{
75
-                              , service = "File_system"
76
-                              , label = Init.LabelSelector.suffix "nix-store"
77
-                              , attributes = toMap { root = "/nix/store" }
78
-                              }
79
-                            , Init.Config.Policy::{
80
-                              , service = "File_system"
81
-                              , label = Init.LabelSelector.prefix "store_rom"
82
-                              , attributes = toMap { root = "/" }
83
-                              }
84
-                            ]
47
+                      )
48
+                  , child
49
+                      "rtc"
50
+                      ( Child.flat
51
+                          Child.Attributes::{
52
+                          , binary = "rtc_drv"
53
+                          , provides = [ "Rtc" ]
54
+                          , routes = [ Init.ServiceRoute.parent "IO_PORT" ]
85 55
                           }
86
-                        , provides = [ "File_system" ]
87
-                        }
88
-                    )
89
-                , child
90
-                    "store_rom"
91
-                    ( Child.flat
92
-                        Child.Attributes::{
93
-                        , binary = "cached_fs_rom"
94
-                        , provides = [ "ROM" ]
95
-                        , resources = Init.Resources::{
96
-                          , ram = storeSize + Genode.units.MiB 1
56
+                      )
57
+                  , child
58
+                      "jitter_sponge"
59
+                      ( Child.flat
60
+                          Child.Attributes::{
61
+                          , binary = "jitter_sponge"
62
+                          , provides = [ "Terminal" ]
63
+                          , config = Init.Config::{
64
+                            , policies =
65
+                              [ Init.Config.Policy::{
66
+                                , service = "Terminal"
67
+                                , label = Init.LabelSelector.suffix "entropy"
68
+                                }
69
+                              ]
70
+                            }
97 71
                           }
98
-                        , config = Init.Config::{
99
-                          , policies =
100
-                                [ Init.Config.Policy::{
101
-                                  , service = "ROM"
102
-                                  , label =
103
-                                      Init.LabelSelector.prefix
104
-                                        "nixos -> /nix/store"
105
-                                  }
106
-                                ]
107
-                              # ( let Entry = Prelude.Map.Entry Text Text
72
+                      )
73
+                  , child
74
+                      "store_rom"
75
+                      ( Child.flat
76
+                          Child.Attributes::{
77
+                          , binary = "cached_fs_rom"
78
+                          , provides = [ "ROM" ]
79
+                          , resources = Init.Resources::{
80
+                            , ram = params.storeSize + Genode.units.MiB 1
81
+                            }
82
+                          , config = Init.Config::{
83
+                            , policies =
84
+                                  [ Init.Config.Policy::{
85
+                                    , service = "ROM"
86
+                                    , label =
87
+                                        Init.LabelSelector.prefix
88
+                                          "nixos -> /nix/store"
89
+                                    , diag = Some True
90
+                                    }
91
+                                  ]
92
+                                # ( let Entry = Prelude.Map.Entry Text Text
108 93
 
109
-                                  in  Prelude.List.concatMap
110
-                                        Entry
111
-                                        Init.Config.Policy.Type
112
-                                        ( λ(e : Entry) →
113
-                                            [ Init.Config.Policy::{
114
-                                              , service = "ROM"
115
-                                              , label =
116
-                                                  Init.LabelSelector.prefix
117
-                                                    "nixos -> ${e.mapKey}"
118
-                                              , attributes = toMap
119
-                                                  { directory =
120
-                                                      "${e.mapValue}/bin"
121
-                                                  }
122
-                                              }
123
-                                            , Init.Config.Policy::{
124
-                                              , service = "ROM"
125
-                                              , label =
126
-                                                  Init.LabelSelector.Type.Partial
127
-                                                    { prefix = Some
128
-                                                        "nixos -> ${e.mapKey}"
129
-                                                    , suffix = Some ".lib.so"
94
+                                    in  Prelude.List.concatMap
95
+                                          Entry
96
+                                          Init.Config.Policy.Type
97
+                                          ( λ(e : Entry) →
98
+                                              [ Init.Config.Policy::{
99
+                                                , service = "ROM"
100
+                                                , diag = Some True
101
+                                               , label =
102
+                                                    Init.LabelSelector.prefix
103
+                                                      "nixos -> ${e.mapKey}"
104
+                                                , attributes = toMap
105
+                                                    { directory =
106
+                                                        "${e.mapValue}/bin"
130 107
                                                     }
131
-                                              , attributes = toMap
132
-                                                  { directory =
133
-                                                      "${e.mapValue}/lib"
134
-                                                  }
135
-                                              }
136
-                                            ]
137
-                                        )
138
-                                        storeRomPolicies
139
-                                )
140
-                          }
141
-                        }
142
-                    )
143
-                , child
144
-                    "nixos"
145
-                    ( Init.toChild
146
-                        subinit
147
-                        Init.Attributes::{
148
-                        , exitPropagate = True
149
-                        , resources = Init.Resources::{
150
-                          , ram = Genode.units.MiB 4
151
-                          }
152
-                        , routes =
153
-                            let parentROMs =
154
-                                  Prelude.List.concatMap
155
-                                    Text
156
-                                    Init.ServiceRoute.Type
157
-                                    ( λ(suffix : Text) →
158
-                                        Prelude.List.map
159
-                                          Text
160
-                                          Init.ServiceRoute.Type
161
-                                          ( λ(prefix : Text) →
162
-                                              { service =
163
-                                                { name = "ROM"
108
+                                                }
109
+                                              , Init.Config.Policy::{
110
+                                                , service = "ROM"
111
+                                                , diag = Some True
164 112
                                                 , label =
165 113
                                                     Init.LabelSelector.Type.Partial
166
-                                                      { prefix = Some prefix
167
-                                                      , suffix = Some suffix
114
+                                                      { prefix = Some
115
+                                                          "nixos -> ${e.mapKey}"
116
+                                                      , suffix = Some ".so"
168 117
                                                       }
118
+                                                , attributes = toMap
119
+                                                    { directory =
120
+                                                        "${e.mapValue}/lib"
121
+                                                    }
169 122
                                                 }
170
-                                              , route =
171
-                                                  Init.Route.parent
172
-                                                    (Some suffix)
173
-                                              }
123
+                                              ]
174 124
                                           )
175
-                                          ( Prelude.Map.keys
176
-                                              Text
177
-                                              Init.Child.Type
178
-                                              subinit.children
179
-                                          )
180
-                                    )
125
+                                          params.storeRomPolicies
126
+                                  )
127
+                            }
128
+                          }
129
+                      )
130
+                  ]
131
+                # params.extraCoreChildren
132
+                # [ child
133
+                      "nixos"
134
+                      ( Init.toChild
135
+                          params.subinit
136
+                          Init.Attributes::{
137
+                          , exitPropagate = True
138
+                          , resources = Init.Resources::{
139
+                            , ram = Genode.units.MiB 4
140
+                            }
141
+                          , routes =
142
+                              let parentROMs =
143
+                                    Prelude.List.concatMap
144
+                                      Text
145
+                                      Init.ServiceRoute.Type
146
+                                      ( λ(suffix : Text) →
147
+                                          Prelude.List.map
148
+                                            Text
149
+                                            Init.ServiceRoute.Type
150
+                                            ( λ(prefix : Text) →
151
+                                                { service =
152
+                                                  { name = "ROM"
153
+                                                  , label =
154
+                                                      Init.LabelSelector.Type.Partial
155
+                                                        { prefix = Some prefix
156
+                                                        , suffix = Some suffix
157
+                                                        }
158
+                                                  }
159
+                                                , route =
160
+                                                    Init.Route.parent
161
+                                                      (Some suffix)
162
+                                                }
163
+                                            )
164
+                                            ( Prelude.Map.keys
165
+                                                Text
166
+                                                Init.Child.Type
167
+                                                params.subinit.children
168
+                                            )
169
+                                      )
181 170
 
182
-                            in    parentROMs
183
-                                    [ "ld.lib.so", "vfs.lib.so", "init" ]
184
-                                # [ Init.ServiceRoute.parent "IO_MEM"
185
-                                  , Init.ServiceRoute.parent "IO_PORT"
186
-                                  , Init.ServiceRoute.parent "IRQ"
187
-                                  , Init.ServiceRoute.parent "VM"
188
-                                  , Init.ServiceRoute.child "Timer" "timer"
189
-                                  , Init.ServiceRoute.child "Rtc" "rtc"
190
-                                  ]
191
-                        }
192
-                    )
193
-                ]
171
+                              in    parentROMs
172
+                                      [ "ld.lib.so", "vfs.lib.so", "init" ]
173
+                                  # [ Init.ServiceRoute.parent "IO_MEM"
174
+                                    , Init.ServiceRoute.parent "IO_PORT"
175
+                                    , Init.ServiceRoute.parent "IRQ"
176
+                                    , Init.ServiceRoute.parent "VM"
177
+                                    , Init.ServiceRoute.child "Timer" "timer"
178
+                                    , Init.ServiceRoute.child "Rtc" "rtc"
179
+                                    ]
180
+                          }
181
+                      )
182
+                  ]
194 183
         }
195 184
       , rom =
196 185
           Genode.BootModules.toRomPaths
@@ -199,7 +188,7 @@ in  λ(subinit : Init.Type) →
199 188
                 ( Prelude.Map.values
200 189
                     Text
201 190
                     (Prelude.Map.Type Text Text)
202
-                    bootManifest
191
+                    params.bootManifest
203 192
                 )
204 193
             )
205 194
       }

+ 1
- 0
tests/lib/build-vms.nix Näytä tiedosto

@@ -29,6 +29,7 @@ rec {
29 29
       baseModules = (import "${modulesPath}/module-list.nix") ++ [
30 30
         ../../nixos-modules/genode-core.nix
31 31
         ../../nixos-modules/genode-init.nix
32
+        ../../nixos-modules/hardware.nix
32 33
         ../../nixos-modules/qemu-vm.nix
33 34
         {
34 35
           key = "no-manual";

Loading…
Peruuta
Tallenna