Genode Packages collection https://git.sr.ht/~ehmry/genodepkgs/
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

genode-core.nix 13KB

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