From ccc2f4f79f7e689d8ecd672bfb73481d50fdc19c Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Thu, 28 Sep 2023 11:49:50 +0100 Subject: [PATCH] =?UTF-8?q?Modify=20type=20of=20ERIS=C2=ADmanifest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the manifest to have a more general type. --- default.nix | 18 +++-- flake.nix | 24 ++++--- nixos-modules/eris/default.nix | 2 +- nixos-modules/genode-core.nix | 34 +++++---- nixos-modules/hardware/default.nix | 8 +-- nixos-modules/lib/children.nix | 13 ++-- overlay/default.nix | 11 +-- overlay/eris-patch-hook/eris_patch.nim | 98 ++++++++++++++++++-------- tests/bash.nix | 6 +- 9 files changed, 136 insertions(+), 78 deletions(-) diff --git a/default.nix b/default.nix index fe35e33..59537f6 100644 --- a/default.nix +++ b/default.nix @@ -60,11 +60,19 @@ let manifest = fromJSON (unsafeDiscardStringContext (readFile "${pkg}/nix-support/eris-manifest.json")); entry = manifest.${filename}; - in entry // { - cap = "(${pkg}/nix-support/eris-manifest.dhall).${filename}.cap"; - path = "${pkg}${ - substring (stringLength pkg) (stringLength entry.path) entry.path - }"; # hack to build a string with context + in { + inherit (entry) cap; + closure = map (ce: + if ce.cap == entry.cap then + ce // { + # hack to build a string with context to propagate a + # dependency on the rest of the closure + path = "${pkg}${ + substring (stringLength pkg) (stringLength ce.path) ce.path + }"; + } + else + ce) entry.closure; }; getErisMainProgram = pkg: diff --git a/flake.nix b/flake.nix index a90b569..df23d00 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,8 @@ nixConfig = { extra-substituters = [ "https://sigil.cachix.org" ]; - extra-trusted-public-keys = [ "sigil.cachix.org-1:poBTiAr1x94vX0ONljw+R22Hmxd5rtHi9UYdHlRaWoM=" ]; + extra-trusted-public-keys = + [ "sigil.cachix.org-1:poBTiAr1x94vX0ONljw+R22Hmxd5rtHi9UYdHlRaWoM=" ]; }; outputs = { self, eris, nixpkgs, nimble }: @@ -84,14 +85,21 @@ manifest = fromJSON (unsafeDiscardStringContext (readFile "${pkg}/nix-support/eris-manifest.json")); entry = manifest.${filename}; - in entry // { - cap = "(${pkg}/nix-support/eris-manifest.dhall).${filename}.cap"; - path = "${pkg}${ - substring (stringLength pkg) (stringLength entry.path) - entry.path - }"; # hack to build a string with context + in { + inherit (entry) cap; + closure = map (ce: + if ce.cap == entry.cap then + ce // { + # hack to build a string with context to propagate a + # dependency on the rest of the closure + path = "${pkg}${ + substring (stringLength pkg) (stringLength ce.path) + ce.path + }"; + } + else + ce) entry.closure; }; - getErisMainProgram = pkg: final.getEris (final.getMainProgram pkg) (prev.getOutput "bin" pkg); diff --git a/nixos-modules/eris/default.nix b/nixos-modules/eris/default.nix index 5233453..53901e2 100644 --- a/nixos-modules/eris/default.nix +++ b/nixos-modules/eris/default.nix @@ -23,7 +23,7 @@ ( VFS.vfs [ VFS.leafAttrs "plugin" - (toMap { load = ${vfsRump.cap}, fs = "cd9660", ram = "12M", writeable="no" }) + (toMap { load = "${vfsRump.cap}", fs = "cd9660", ram = "12M", writeable="no" }) ] ) ''; diff --git a/nixos-modules/genode-core.nix b/nixos-modules/genode-core.nix index dbbce7b..c2d0c2d 100644 --- a/nixos-modules/genode-core.nix +++ b/nixos-modules/genode-core.nix @@ -107,7 +107,7 @@ let let XML = Sigil.Prelude.XML in ${./store-wrapper.dhall} - { binaries.rtc_drv = ${rtc_drv.cap} + { binaries.rtc_drv = "${rtc_drv.cap}" , extraCoreChildren = ${extraCoreChildren} , subinit = ${config.genode.init.configFile} , storeSize = $(stat --format '%s' ${tarball}) @@ -232,20 +232,24 @@ in { }]; genode.core.romModules = with builtins; - (lib.lists.flatten ((map (getAttr "roms") (attrValues children')) ++ (map - ({ cap, path, ... }: { - name = cap; - value = path; - }) (attrValues coreErisCaps)))) ++ [ - { - name = ''"init"''; - value = "${pkgs.genodePackages.init}/bin/init"; - } - { - name = ''"report_rom"''; - value = "${pkgs.genodePackages.report_rom}/bin/report_rom"; - } - ]; + let + childRomEntries = + lib.lists.flatten (map (getAttr "roms") (attrValues children')); + coreErisCapEntries = lib.lists.flatten (map ({ cap, closure }: + map ({ cap, path }: { + name = ''"${cap}"''; + value = path; + }) closure) (attrValues coreErisCaps)); + in childRomEntries ++ coreErisCapEntries ++ [ + { + name = ''"init"''; + value = "${pkgs.genodePackages.init}/bin/init"; + } + { + name = ''"report_rom"''; + value = "${pkgs.genodePackages.report_rom}/bin/report_rom"; + } + ]; genode.core.children.jitter_sponge = { package = pkgs.genodePackages.jitter_sponge; diff --git a/nixos-modules/hardware/default.nix b/nixos-modules/hardware/default.nix index 62b0ae6..81307cb 100644 --- a/nixos-modules/hardware/default.nix +++ b/nixos-modules/hardware/default.nix @@ -32,15 +32,15 @@ in { ahciConfig = lib.optionalString cfg.ahci.enable (with cfg.ahci; '' , ahci_drv = Some { - , binary = ${ahciEris.cap} + , binary = "${ahciEris.cap}" , atapi = ${toDhall atapiSupport} } ''); usbConfig = lib.optionalString cfg.usb.enable (with cfg.usb.host; '' - , usb_block_drv = Some { binary = ${usbEris.usb_block_drv.cap} } + , usb_block_drv = Some { binary = "${usbEris.usb_block_drv.cap}" } , usb_host_drv = Some { - , binary = ${usbEris.usb_host_drv.cap} + , binary = "${usbEris.usb_host_drv.cap}" , bios_handoff = ${toDhall biosHandoff} , ehci = ${toDhall ehciSupport} , ohci = ${toDhall ohciSupport} @@ -54,7 +54,7 @@ in { in Manager.toChildAttributes Manager::{ - , part_block.binary = ${partBlockEris.cap} + , part_block.binary = "${partBlockEris.cap}" ${ahciConfig} ${usbConfig} , verbose = ${toDhall cfg.verbose} diff --git a/nixos-modules/lib/children.nix b/nixos-modules/lib/children.nix index 4eb1943..88c8185 100644 --- a/nixos-modules/lib/children.nix +++ b/nixos-modules/lib/children.nix @@ -73,14 +73,11 @@ lib.attrsets.mapAttrs (_: { binary, configFile, extraErisInputs, package, ... }: let - toRoms = { cap, closure, path }: - [{ - name = cap; + toRoms = { closure, ... }: + map ({ cap, path }: { + name = ''"${cap}"''; value = path; - }] ++ (lib.mapAttrsToList (name: value: { - name = ''"${value}"''; - value = name; - }) closure); + }) closure; extraRoms = map toRoms extraErisInputs; in if binary != null then { config = ''${configFile} "${binary}"''; @@ -88,7 +85,7 @@ } else let bin = lib.getErisMainProgram package; in { - config = "${configFile} ${bin.cap}"; + config = ''${configFile} "${bin.cap}"''; roms = toRoms bin ++ extraRoms; }) children; }; diff --git a/overlay/default.nix b/overlay/default.nix index 2544e19..3660a2d 100644 --- a/overlay/default.nix +++ b/overlay/default.nix @@ -264,10 +264,13 @@ in nullPkgs // { solo5-tools = callPackage ./solo5-tools { }; - stdenv = overrideHost (old: { - extraNativeBuildInputs = old.extraNativeBuildInputs - ++ [ final.buildPackages.erisPatchHook ]; - }) prev.stdenv; + stdenv = if prev.stdenv.hostPlatform.isGenode then + stdenv.override (prev': { + extraNativeBuildInputs = prev'.extraNativeBuildInputs + ++ [ final.buildPackages.erisPatchHook ]; + }) + else + prev.stdenv; tor = overrideAttrsHost (attrs: { patches = attrs.patches or [ ] ++ [ diff --git a/overlay/eris-patch-hook/eris_patch.nim b/overlay/eris-patch-hook/eris_patch.nim index c5b17d1..8eaf477 100644 --- a/overlay/eris-patch-hook/eris_patch.nim +++ b/overlay/eris-patch-hook/eris_patch.nim @@ -3,6 +3,26 @@ import cbor, dhall/[render, terms], eris const selfDescribedCbor = 55799 +type + Manifest = Table[string, ManifestEntry] + ManifestEntry = object + path: string + closure: Table[string, ErisCap] + +proc parseManifestFile(path: string): Manifest = + let js = parseFile(path) + for key, val in js.pairs: + var + entry: ManifestEntry + entryCap = val["cap"].getStr.parseErisUrn + for e in val["closure"].items: + var + cap = e["cap"].getStr.parseErisUrn + path = e["path"].getStr + if cap == entryCap: entry.path = path + entry.closure[path] = cap + result[key] = entry + proc writeErisLinks(path: string; node: CborNode) = # Inspired by "Package Metadata for Core Files" # - https://systemd.io/COREDUMP_PACKAGE_METADATA/ @@ -25,16 +45,31 @@ proc toCbor(cap: ErisCap): CborNode = result = initCborBytes(cap.bytes) result.tag = erisCborTag -proc toDhall(js: JsonNode): Value = - case js.kind - of JString: - result = newValue(js.str) - of JObject: - result = newRecordLiteral(js.fields.len) - for key, val in js.fields.pairs: - result.table[key] = val.toDhall - else: - raiseAssert "unhandled JSON value" +proc toDhall(entry: ManifestEntry): Value = + var closure = newSeqOfCap[Value](entry.closure.len) + for path, cap in entry.closure.pairs: + closure.add newRecordLiteral( + { "cap": newValue $cap, "path": newValue path }) + newRecordLiteral { + "cap": newValue $(entry.closure[entry.path]), + "closure": newValue closure, + } + +proc toDhall(manifest: Manifest): Value = + result = newRecordLiteral(manifest.len) + for name, entry in manifest.pairs: + result.table[name] = entry.toDhall + +proc toJson(entry: ManifestEntry): JsonNode = + var closure = newJArray() + for path, cap in entry.closure.pairs: + closure.add %*{ "cap": %($cap), "path": %path } + %*{ "cap": %($entry.closure[entry.path]), "closure": closure } + +proc toJson(manifest: Manifest): JsonNode = + result = newJObject() + for name, entry in manifest.pairs: + result[name] = entry.toJSON proc isElf(path: string): bool = var magic: array[4, char] @@ -66,7 +101,7 @@ proc main = erisLinks: CborNode var - outputManifests = initTable[string, JsonNode]() + outputManifests = initTable[string, Manifest]() pendingFiles = initDeque[PendingFile]() failed = false if getEnv("outputs") == "": @@ -78,7 +113,7 @@ proc main = if fileExists(outputRoot / jsonManifestSubPath): stderr.writeLine "Not running ERIS patch hook again" quit 0 - outputManifests[outputRoot] = newJObject() + outputManifests[outputRoot] = Manifest() let buildInputs = getEnv("buildInputs").splitWhitespace @@ -149,14 +184,15 @@ proc main = let manifestPath = storePath / jsonManifestSubPath if fileExists(manifestPath): let - manifest = parseFile(manifestPath) + manifest = parseManifestFile(manifestPath) entry = manifest[filePath.extractFilename] - for path, urn in entry["closure"].pairs: - result[path] = parseErisUrn urn.getStr - let otherClosure = fileClosure(path) - for otherPath, otherCap in otherClosure.pairs: - # merge the closure of the dependency - result[otherPath] = otherCap + for path, cap in entry.closure.pairs: + if path != filePath: + result[path] = cap + let otherClosure = fileClosure(path) + for otherPath, otherCap in otherClosure.pairs: + # merge the closure of the dependency + result[otherPath] = otherCap closureCache[filePath] = result for outputRoot in outputManifests.keys: @@ -196,7 +232,7 @@ proc main = pendingFiles.addLast(pendingFile) break selfReferenceCheck var - closure = newJObject() + closure = initTable[string, ErisCap]() replaceCmd = patchelf & " --set-rpath '' " & filePath for need, replacementPath in pendingFile.replacements.pairs: if replacementPath == "": continue @@ -204,11 +240,11 @@ proc main = cap = fileCap(replacementPath) urn = $cap stderr.writeLine "replace reference to ", need, " with ", urn - closure[replacementPath] = %urn - pendingFile.erisLinks[ replacementPath.toCbor] = cap.toCbor + closure[replacementPath] = cap + pendingFile.erisLinks[replacementPath.toCbor] = cap.toCbor replaceCmd.add(" --replace-needed $# $#" % [need, urn]) for path, cap in fileClosure(replacementPath).pairs: - closure[path] = %($cap) + closure[path] = cap pendingFile.erisLinks[path.toCbor] = cap.toCbor if runPatchelf and pendingFile.replacements.len != 0: @@ -238,11 +274,13 @@ proc main = quit("Adding note to $1 failed" % pendingFile.filePath) moveFile(tmpFile, pendingFile.filePath) - outputManifests[pendingFile.outputRoot][filePath.extractFilename] = %* { - "cap": $fileCap(filePath), - "closure": closure, - "path": filePath - } + var cap = fileCap(filePath) + closure[filePath] = cap + outputManifests[pendingFile.outputRoot][filePath.extractFilename] = + ManifestEntry( + closure: closure, + path: filePath, + ) if pendingFiles.len == prevPrevLen: failed = true @@ -260,7 +298,7 @@ proc main = for outputRoot, manifest in outputManifests: let supportDir = outputRoot / "nix-support" createDir(supportDir) - writeFile(outputRoot / jsonManifestSubPath, $manifest) - writeFile(outputRoot / dhallManifestSubPath, $(manifest.toDhall)) + writeFile(outputRoot / jsonManifestSubPath, $manifest.toJson) + writeFile(outputRoot / dhallManifestSubPath, $manifest.toDhall) main() diff --git a/tests/bash.nix b/tests/bash.nix index 0c603d9..852b3d2 100644 --- a/tests/bash.nix +++ b/tests/bash.nix @@ -24,9 +24,9 @@ ${./bash.dhall} { , bash = "${pkgs.bash}" , coreutils = "${pkgs.coreutils}" - , cached_fs_rom = ${extraErisInputs'.cached_fs_rom.cap} - , vfs = ${extraErisInputs'.vfs.cap} - , vfs_pipe = ${extraErisInputs'.vfs_pipe.cap} + , cached_fs_rom = "${extraErisInputs'.cached_fs_rom.cap}" + , vfs = "${extraErisInputs'.vfs.cap}" + , vfs_pipe = "${extraErisInputs'.vfs_pipe.cap}" } ''; extraInputs = with pkgs.genodePackages; [ pkgs.bash libc posix ];