treewide: move build helper to more fitting places
Change-Id: I3d0cfe9283222d403ae369ec9db09201ad511e15
Reviewed-on: https://review.monogon.dev/c/monogon/+/3327
Reviewed-by: Serge Bazanski <serge@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/build/gotoolwrap/BUILD.bazel b/metropolis/build/gotoolwrap/BUILD.bazel
deleted file mode 100644
index 281f4b3..0000000
--- a/metropolis/build/gotoolwrap/BUILD.bazel
+++ /dev/null
@@ -1,14 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
-
-go_library(
- name = "gotoolwrap_lib",
- srcs = ["main.go"],
- importpath = "source.monogon.dev/metropolis/build/gotoolwrap",
- visibility = ["//visibility:private"],
-)
-
-go_binary(
- name = "gotoolwrap",
- embed = [":gotoolwrap_lib"],
- visibility = ["//visibility:public"],
-)
diff --git a/metropolis/build/gotoolwrap/main.go b/metropolis/build/gotoolwrap/main.go
deleted file mode 100644
index 343b7ff..0000000
--- a/metropolis/build/gotoolwrap/main.go
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright 2020 The Monogon Project Authors.
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// gotoolwrap is a tiny wrapper used to run executables that expect a standard
-// Go development environment setup to act on the monogon workspace. Notably,
-// it's used in Bazel rules to run tools like gofmt when invoked by some kinds
-// of code generation tools.
-//
-// Usage: ./gotoolwrap executable arg1 arg2
-//
-// gotoolwrap expects the following environment variables to be set (and unsets
-// them before calling the given executable):
-// - GOTOOLWRAP_GOPATH: A synthetic GOPATH, eg. one generated by rules_go's
-// go_path target.
-// - GOTOOLWRAP_GOROOT: A Go SDK's GOROOT, eg. one from rules_go's GoSDK
-// provider.
-// - GOTOOLWRAP_COPYOUT: Pairs of source:destination elements separated by ;.
-// Files given in this list will be copied from source
-// (relative to the GOPATH sources) to the destination
-// (absolute path). This is primarily useful when dealing
-// with code generators which insist on putting their
-// generated files within the GOPATH, and allows copying
-// of said files to a declared output file.
-//
-// gotoolwrap will set PATH to contain GOROOT/bin, and set GOPATH and GOROOT as
-// resolved, absolute paths. Absolute paths are expected by tools like 'gofmt'.
-
-package main
-
-import (
- "errors"
- "fmt"
- "log"
- "os"
- "os/exec"
- "path/filepath"
- "strings"
-)
-
-func main() {
- gopath := os.Getenv("GOTOOLWRAP_GOPATH")
- if gopath == "" {
- log.Fatal("GOTOOLWRAP_GOPATH must be set")
- }
-
- goroot := os.Getenv("GOTOOLWRAP_GOROOT")
- if goroot == "" {
- log.Fatal("GOTOOLWRAP_GOROOT must be set")
- }
-
- if len(os.Args) < 2 {
- log.Fatalf("No command specified")
- }
-
- // Resolve gopath and goroot to absolute paths.
- gopathAbs, err := filepath.Abs(gopath)
- if err != nil {
- log.Fatalf("Abs(%q): %v", gopath, err)
- }
- gorootAbs, err := filepath.Abs(goroot)
- if err != nil {
- log.Fatalf("Abs(%q): %v", goroot, err)
- }
-
- // Ensure the resolved GOROOT has a bin/go and bin/gofmt.
- gorootBin := filepath.Join(gorootAbs, "bin")
- stat, err := os.Stat(gorootBin)
- if err != nil {
- log.Fatalf("Could not stat $GOTOOLWRAP_GOROOT/bin (%q): %v", gorootBin, err)
- }
- if !stat.IsDir() {
- log.Fatalf("$GOTOOLWRAP_GOROOT/bin (%q) is not a directory", gorootBin)
- }
- // We list all files inside so that we can print them to the user for
- // debugging purposes if that's not the case.
- binFiles := make(map[string]bool)
- files, err := os.ReadDir(gorootBin)
- if err != nil {
- log.Fatalf("Could not read dir $GOTOOLWRAP_GOROOT/bin (%q): %v", gorootBin, err)
- }
- for _, f := range files {
- if f.IsDir() {
- continue
- }
- binFiles[f.Name()] = true
- }
- if !binFiles["go"] || !binFiles["gofmt"] {
- msg := "no files"
- if len(binFiles) > 0 {
- var names []string
- for name := range binFiles {
- names = append(names, fmt.Sprintf("%q", name))
- }
- msg = fmt.Sprintf(": %s", strings.Join(names, ", "))
- }
- log.Fatalf("$GOTOOLWRAP_GOROOT/bin (%q) does not contain go and/or gofmt, found %s", gorootBin, msg)
- }
-
- // Make new PATH.
- path := os.Getenv("PATH")
- if path == "" {
- path = gorootBin
- } else {
- path = fmt.Sprintf("%s:%s", gorootBin, path)
- }
-
- cmd := exec.Command(os.Args[1], os.Args[2:]...)
-
- // Copy current env into command's env, filtering out GOTOOLWRAP env vars
- // and PATH (which we set ourselves).
- for _, v := range os.Environ() {
- if strings.HasPrefix(v, "GOTOOLWRAP_GOROOT=") {
- continue
- }
- if strings.HasPrefix(v, "GOTOOLWRAP_GOPATH=") {
- continue
- }
- if strings.HasPrefix(v, "GOTOOLWRAP_COPYOUT=") {
- continue
- }
- if strings.HasPrefix(v, "PATH=") {
- continue
- }
- cmd.Env = append(cmd.Env, v)
- }
- // Create a temporary cache directory and remove everything afterwards.
- // Based on code from
- // @io_bazel_rules_go//go/tools/builders:stdliblist.go L174
- tempDir, err := os.MkdirTemp("", "gocache")
- if err != nil {
- log.Fatalf("Cannot create temporary directory: %v", err)
- }
- defer os.RemoveAll(tempDir)
-
- cmd.Env = append(cmd.Env,
- "GOROOT="+gorootAbs,
- "GOPATH="+gopathAbs,
- "PATH="+path,
- "GO111MODULE=off",
- "GOCACHE="+tempDir,
- )
-
- // Run the command interactively.
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- cmd.Stdin = os.Stdin
- if err := cmd.Run(); err != nil {
- var exitErr *exec.ExitError
- if errors.As(err, &exitErr) {
- os.Exit(exitErr.ExitCode())
- } else {
- log.Fatalf("Could not run %q: %v", os.Args[1], err)
- }
- }
-
- copyout := os.Getenv("GOTOOLWRAP_COPYOUT")
- if len(copyout) != 0 {
- for _, pair := range strings.Split(copyout, ";") {
- parts := strings.Split(pair, ":")
- if len(parts) != 2 {
- log.Fatalf("GOTOOL_COPYOUT invalid pair: %q", pair)
- }
- from := filepath.Join(gopathAbs, "src", parts[0])
- to := parts[1]
- log.Printf("gotoolwrap: Copying %s to %s...", from, to)
- data, err := os.ReadFile(from)
- if err != nil {
- log.Fatalf("gotoolwrap: read failed: %v", err)
- }
- err = os.MkdirAll(filepath.Dir(to), 0755)
- if err != nil {
- log.Fatalf("gotoolwrap: mkdir failed: %v", err)
- }
- err = os.WriteFile(to, data, 0644)
- if err != nil {
- log.Fatalf("gotoolwrap: write failed: %v", err)
- }
- }
- }
-}
diff --git a/metropolis/build/kube-code-generator/boilerplate.go.txt b/metropolis/build/kube-code-generator/boilerplate.go.txt
index ef05f6f..c097ae1 100644
--- a/metropolis/build/kube-code-generator/boilerplate.go.txt
+++ b/metropolis/build/kube-code-generator/boilerplate.go.txt
@@ -1 +1 @@
-// Code generated by //metropolis/build/kubernetes-code-generator. Do not commit to source control.
+// Code generated by //osbase/build/kubernetes-code-generator. Do not commit to source control.
diff --git a/metropolis/build/kube-code-generator/defs.bzl b/metropolis/build/kube-code-generator/defs.bzl
index 7d431ef..2bc32bf 100644
--- a/metropolis/build/kube-code-generator/defs.bzl
+++ b/metropolis/build/kube-code-generator/defs.bzl
@@ -168,7 +168,7 @@
)
# _gotool_run is a helper function which runs an executable under
-# //metropolis/build/gotoolwrap, effectively setting up everything required to
+# //osbase/build/gotoolwrap, effectively setting up everything required to
# use standard Go tooling on the monogon workspace (ie. GOPATH/GOROOT). This is
# required by generators to run 'go fmt'.
#
@@ -524,7 +524,7 @@
default = "@io_bazel_rules_go//:go_context_data",
),
"_gotoolwrap": attr.label(
- default = Label("//metropolis/build/gotoolwrap"),
+ default = Label("//build/gotoolwrap"),
allow_single_file = True,
executable = True,
cfg = "exec",
diff --git a/metropolis/installer/BUILD.bazel b/metropolis/installer/BUILD.bazel
index a0d1993..29eac44 100644
--- a/metropolis/installer/BUILD.bazel
+++ b/metropolis/installer/BUILD.bazel
@@ -1,7 +1,7 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
-load("//metropolis/node/build:def.bzl", "node_initramfs")
-load("//metropolis/node/build/genosrelease:defs.bzl", "os_release")
-load("//metropolis/node/build:efi.bzl", "efi_unified_kernel_image")
+load("//osbase/build:def.bzl", "node_initramfs")
+load("//osbase/build/genosrelease:defs.bzl", "os_release")
+load("//osbase/build:efi.bzl", "efi_unified_kernel_image")
go_library(
name = "installer_lib",
@@ -15,8 +15,8 @@
importpath = "source.monogon.dev/metropolis/installer",
visibility = ["//visibility:private"],
deps = [
- "//metropolis/node/build/mkimage/osimage",
"//osbase/blockdev",
+ "//osbase/build/mkimage/osimage",
"//osbase/efivarfs",
"//osbase/sysfs",
"@org_golang_x_sys//unix",
@@ -35,7 +35,7 @@
"//metropolis/installer": "/init",
},
fsspecs = [
- "//metropolis/node/build:earlydev.fsspec",
+ "//osbase/build:earlydev.fsspec",
],
visibility = ["//metropolis/installer/test:__pkg__"],
)
diff --git a/metropolis/installer/main.go b/metropolis/installer/main.go
index bc428a0..e2d0d55 100644
--- a/metropolis/installer/main.go
+++ b/metropolis/installer/main.go
@@ -34,8 +34,8 @@
"golang.org/x/sys/unix"
- "source.monogon.dev/metropolis/node/build/mkimage/osimage"
"source.monogon.dev/osbase/blockdev"
+ "source.monogon.dev/osbase/build/mkimage/osimage"
"source.monogon.dev/osbase/efivarfs"
"source.monogon.dev/osbase/sysfs"
)
diff --git a/metropolis/installer/test/BUILD.bazel b/metropolis/installer/test/BUILD.bazel
index 3f74cde..9971209 100644
--- a/metropolis/installer/test/BUILD.bazel
+++ b/metropolis/installer/test/BUILD.bazel
@@ -1,5 +1,5 @@
load("@io_bazel_rules_go//go:def.bzl", "go_test")
-load("//metropolis/node/build:efi.bzl", "efi_unified_kernel_image")
+load("//osbase/build:efi.bzl", "efi_unified_kernel_image")
go_test(
name = "test_test",
@@ -23,8 +23,8 @@
},
deps = [
"//metropolis/cli/metroctl/core",
- "//metropolis/node/build/mkimage/osimage",
"//metropolis/proto/api",
+ "//osbase/build/mkimage/osimage",
"//osbase/cmd",
"@com_github_diskfs_go_diskfs//:go-diskfs",
"@com_github_diskfs_go_diskfs//disk",
diff --git a/metropolis/installer/test/run_test.go b/metropolis/installer/test/run_test.go
index fef8e20..64fa210 100644
--- a/metropolis/installer/test/run_test.go
+++ b/metropolis/installer/test/run_test.go
@@ -38,7 +38,7 @@
"source.monogon.dev/metropolis/proto/api"
mctl "source.monogon.dev/metropolis/cli/metroctl/core"
- "source.monogon.dev/metropolis/node/build/mkimage/osimage"
+ "source.monogon.dev/osbase/build/mkimage/osimage"
"source.monogon.dev/osbase/cmd"
)
diff --git a/metropolis/installer/test/testos/BUILD.bazel b/metropolis/installer/test/testos/BUILD.bazel
index 8d5f267..d1ae0df 100644
--- a/metropolis/installer/test/testos/BUILD.bazel
+++ b/metropolis/installer/test/testos/BUILD.bazel
@@ -1,6 +1,6 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
-load("//metropolis/node/build:def.bzl", "erofs_image", "verity_image")
-load("//metropolis/node/build:efi.bzl", "efi_unified_kernel_image")
+load("//osbase/build:def.bzl", "erofs_image", "verity_image")
+load("//osbase/build:efi.bzl", "efi_unified_kernel_image")
load("@rules_pkg//:pkg.bzl", "pkg_zip")
erofs_image(
diff --git a/metropolis/node/BUILD.bazel b/metropolis/node/BUILD.bazel
index 6354edc..a0847f8 100644
--- a/metropolis/node/BUILD.bazel
+++ b/metropolis/node/BUILD.bazel
@@ -1,7 +1,7 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
-load("//metropolis/node/build:def.bzl", "erofs_image", "verity_image")
-load("//metropolis/node/build:efi.bzl", "efi_unified_kernel_image")
-load("//metropolis/node/build/mkimage:def.bzl", "node_image")
+load("//osbase/build:def.bzl", "erofs_image", "verity_image")
+load("//osbase/build:efi.bzl", "efi_unified_kernel_image")
+load("//osbase/build/mkimage:def.bzl", "node_image")
load("@rules_pkg//:pkg.bzl", "pkg_zip")
go_library(
@@ -89,7 +89,7 @@
},
fsspecs = [
":erofs-layout.fsspec",
- "//metropolis/node/build:earlydev.fsspec",
+ "//osbase/build:earlydev.fsspec",
"//third_party:firmware",
],
symlinks = {
@@ -135,7 +135,7 @@
],
)
-load("//metropolis/node/build/genosrelease:defs.bzl", "os_release")
+load("//osbase/build/genosrelease:defs.bzl", "os_release")
os_release(
name = "os-release-info",
diff --git a/metropolis/node/build/BUILD.bazel b/metropolis/node/build/BUILD.bazel
deleted file mode 100644
index 8eafa9d..0000000
--- a/metropolis/node/build/BUILD.bazel
+++ /dev/null
@@ -1 +0,0 @@
-exports_files(["earlydev.fsspec"])
diff --git a/metropolis/node/build/def.bzl b/metropolis/node/build/def.bzl
deleted file mode 100644
index d56d78a..0000000
--- a/metropolis/node/build/def.bzl
+++ /dev/null
@@ -1,403 +0,0 @@
-# Copyright 2020 The Monogon Project Authors.
-#
-# SPDX-License-Identifier: Apache-2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-load("@bazel_skylib//lib:paths.bzl", "paths")
-
-def _build_pure_transition_impl(settings, attr):
- """
- Transition that enables pure, static build of Go binaries.
- """
- race = settings['@io_bazel_rules_go//go/config:race']
- pure = not race
-
- return {
- "@io_bazel_rules_go//go/config:pure": pure,
- "@io_bazel_rules_go//go/config:static": True,
- }
-
-build_pure_transition = transition(
- implementation = _build_pure_transition_impl,
- inputs = [
- "@io_bazel_rules_go//go/config:race",
- ],
- outputs = [
- "@io_bazel_rules_go//go/config:pure",
- "@io_bazel_rules_go//go/config:static",
- ],
-)
-
-def _build_static_transition_impl(settings, attr):
- """
- Transition that enables static builds with CGo and musl for Go binaries.
- """
- return {
- "@io_bazel_rules_go//go/config:static": True,
- "//command_line_option:platforms": "//build/platforms:linux_amd64_static",
- }
-
-build_static_transition = transition(
- implementation = _build_static_transition_impl,
- inputs = [],
- outputs = [
- "@io_bazel_rules_go//go/config:static",
- "//command_line_option:platforms",
- ],
-)
-
-FSSpecInfo = provider(
- "Provides parts of an FSSpec used to assemble filesystem images",
- fields = {
- "spec": "File containing the partial FSSpec as prototext",
- "referenced": "Files (potentially) referenced by the spec",
- },
-)
-
-def _fsspec_core_impl(ctx, tool, output_file):
- """
- _fsspec_core_impl implements the core of an fsspec-based rule. It takes
- input from the `files`,`files_cc`, `symlinks` and `fsspecs` attributes
- and calls `tool` with the `-out` parameter pointing to `output_file`
- and paths to all fsspecs as positional arguments.
- """
- fs_spec_name = ctx.label.name + ".prototxt"
- fs_spec = ctx.actions.declare_file(fs_spec_name)
-
- fs_files = []
- inputs = []
- for label, p in ctx.attr.files.items() + ctx.attr.files_cc.items():
- if not p.startswith("/"):
- fail("file {} invalid: must begin with /".format(p))
-
- # Figure out if this is an executable.
- is_executable = True
-
- di = label[DefaultInfo]
- if di.files_to_run.executable == None:
- # Generated non-executable files will have DefaultInfo.files_to_run.executable == None
- is_executable = False
- elif di.files_to_run.executable.is_source:
- # Source files will have executable.is_source == True
- is_executable = False
-
- # Ensure only single output is declared.
- # If you hit this error, figure out a better logic to find what file you need, maybe looking at providers other
- # than DefaultInfo.
- files = di.files.to_list()
- if len(files) > 1:
- fail("file {} has more than one output: {}", p, files)
- src = files[0]
- inputs.append(src)
-
- mode = 0o555 if is_executable else 0o444
- fs_files.append(struct(path = p, source_path = src.path, mode = mode, uid = 0, gid = 0))
-
- fs_symlinks = []
- for target, p in ctx.attr.symlinks.items():
- fs_symlinks.append(struct(path = p, target_path = target))
-
- fs_spec_content = struct(file = fs_files, directory = [], symbolic_link = fs_symlinks)
- ctx.actions.write(fs_spec, proto.encode_text(fs_spec_content))
-
- extra_specs = []
-
- for fsspec in ctx.attr.fsspecs:
- if FSSpecInfo in fsspec:
- fsspecInfo = fsspec[FSSpecInfo]
- extra_specs.append(fsspecInfo.spec)
- for f in fsspecInfo.referenced:
- inputs.append(f)
- else:
- # Raw .fsspec prototext. No referenced data allowed.
- di = fsspec[DefaultInfo]
- extra_specs += di.files.to_list()
-
- ctx.actions.run(
- outputs = [output_file],
- inputs = [fs_spec] + inputs + extra_specs,
- tools = [tool],
- executable = tool,
- arguments = ["-out", output_file.path, fs_spec.path] + [s.path for s in extra_specs],
- )
- return
-
-def _node_initramfs_impl(ctx):
- initramfs_name = ctx.label.name + ".cpio.zst"
- initramfs = ctx.actions.declare_file(initramfs_name)
-
- _fsspec_core_impl(ctx, ctx.executable._mkcpio, initramfs)
-
- # TODO(q3k): Document why this is needed
- return [DefaultInfo(runfiles = ctx.runfiles(files = [initramfs]), files = depset([initramfs]))]
-
-node_initramfs = rule(
- implementation = _node_initramfs_impl,
- doc = """
- Build a node initramfs. The initramfs will contain a basic /dev directory and all the files specified by the
- `files` attribute. Executable files will have their permissions set to 0755, non-executable files will have
- their permissions set to 0444. All parent directories will be created with 0755 permissions.
- """,
- attrs = {
- "files": attr.label_keyed_string_dict(
- mandatory = True,
- allow_files = True,
- doc = """
- Dictionary of Labels to String, placing a given Label's output file in the initramfs at the location
- specified by the String value. The specified labels must only have a single output.
- """,
- # Attach pure transition to ensure all binaries added to the initramfs are pure/static binaries.
- cfg = build_pure_transition,
- ),
- "files_cc": attr.label_keyed_string_dict(
- allow_files = True,
- doc = """
- Special case of 'files' for compilation targets that need to be built with the musl toolchain like
- go_binary targets which need cgo or cc_binary targets.
- """,
- # Attach static transition to all files_cc inputs to ensure they are built with musl and static.
- cfg = build_static_transition,
- ),
- "symlinks": attr.string_dict(
- default = {},
- doc = """
- Symbolic links to create. Similar format as in files and files_cc, so the target of the symlink is the
- key and the value of it is the location of the symlink itself. Only raw strings are allowed as targets,
- labels are not permitted. Include the file using files or files_cc, then symlink to its location.
- """,
- ),
- "fsspecs": attr.label_list(
- default = [],
- doc = """
- List of file system specs (metropolis.node.build.fsspec.FSSpec) to also include in the resulting image.
- These will be merged with all other given attributes.
- """,
- providers = [FSSpecInfo],
- allow_files = True,
- ),
-
- # Tool
- "_mkcpio": attr.label(
- default = Label("//metropolis/node/build/mkcpio"),
- executable = True,
- cfg = "exec",
- ),
- },
-)
-
-def _erofs_image_impl(ctx):
- fs_name = ctx.label.name + ".img"
- fs_out = ctx.actions.declare_file(fs_name)
-
- _fsspec_core_impl(ctx, ctx.executable._mkerofs, fs_out)
-
- return [DefaultInfo(files = depset([fs_out]))]
-
-erofs_image = rule(
- implementation = _erofs_image_impl,
- doc = """
- Build an EROFS. All files specified in files, files_cc and all specified symlinks will be contained.
- Executable files will have their permissions set to 0555, non-executable files will have
- their permissions set to 0444. All parent directories will be created with 0555 permissions.
- """,
- attrs = {
- "files": attr.label_keyed_string_dict(
- mandatory = True,
- allow_files = True,
- doc = """
- Dictionary of Labels to String, placing a given Label's output file in the EROFS at the location
- specified by the String value. The specified labels must only have a single output.
- """,
- # Attach pure transition to ensure all binaries added to the initramfs are pure/static binaries.
- cfg = build_pure_transition,
- ),
- "files_cc": attr.label_keyed_string_dict(
- allow_files = True,
- doc = """
- Special case of 'files' for compilation targets that need to be built with the musl toolchain like
- go_binary targets which need cgo or cc_binary targets.
- """,
- # Attach static transition to all files_cc inputs to ensure they are built with musl and static.
- cfg = build_static_transition,
- ),
- "symlinks": attr.string_dict(
- default = {},
- doc = """
- Symbolic links to create. Similar format as in files and files_cc, so the target of the symlink is the
- key and the value of it is the location of the symlink itself. Only raw strings are allowed as targets,
- labels are not permitted. Include the file using files or files_cc, then symlink to its location.
- """,
- ),
- "fsspecs": attr.label_list(
- default = [],
- doc = """
- List of file system specs (metropolis.node.build.fsspec.FSSpec) to also include in the resulting image.
- These will be merged with all other given attributes.
- """,
- providers = [FSSpecInfo],
- allow_files = True,
- ),
-
- # Tools, implicit dependencies.
- "_mkerofs": attr.label(
- default = Label("//metropolis/node/build/mkerofs"),
- executable = True,
- cfg = "host",
- ),
- },
-)
-
-# VerityConfig is emitted by verity_image, and contains a file enclosing a
-# singular dm-verity target table.
-VerityConfig = provider(
- "Configuration necessary to mount a single dm-verity target.",
- fields = {
- "table": "A file containing the dm-verity target table. See: https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/verity.html",
- },
-)
-
-def _verity_image_impl(ctx):
- """
- Create a new file containing the source image data together with the Verity
- metadata appended to it, and provide an associated DeviceMapper Verity target
- table in a separate file, through VerityConfig provider.
- """
-
- # Run mkverity.
- image = ctx.actions.declare_file(ctx.attr.name + ".img")
- table = ctx.actions.declare_file(ctx.attr.name + ".dmt")
- ctx.actions.run(
- mnemonic = "GenVerityImage",
- progress_message = "Generating a dm-verity image",
- inputs = [ctx.file.source],
- outputs = [
- image,
- table,
- ],
- executable = ctx.file._mkverity,
- arguments = [
- "-input=" + ctx.file.source.path,
- "-output=" + image.path,
- "-table=" + table.path,
- "-data_alias=" + ctx.attr.rootfs_partlabel,
- "-hash_alias=" + ctx.attr.rootfs_partlabel,
- ],
- )
-
- return [
- DefaultInfo(
- files = depset([image]),
- runfiles = ctx.runfiles(files = [image]),
- ),
- VerityConfig(
- table = table,
- ),
- ]
-
-verity_image = rule(
- implementation = _verity_image_impl,
- doc = """
- Build a dm-verity target image by appending Verity metadata to the source
- image. A corresponding dm-verity target table will be made available
- through VerityConfig provider.
- """,
- attrs = {
- "source": attr.label(
- doc = "A source image.",
- allow_single_file = True,
- ),
- "rootfs_partlabel": attr.string(
- doc = "GPT partition label of the rootfs to be used with dm-mod.create.",
- default = "PARTLABEL=METROPOLIS-SYSTEM-X",
- ),
- "_mkverity": attr.label(
- doc = "The mkverity executable needed to generate the image.",
- default = "//metropolis/node/build/mkverity",
- allow_single_file = True,
- executable = True,
- cfg = "host",
- ),
- },
-)
-
-# From Aspect's bazel-lib under Apache 2.0
-def _transition_platform_impl(_, attr):
- return {"//command_line_option:platforms": str(attr.target_platform)}
-
-# Transition from any input configuration to one that includes the
-# --platforms command-line flag.
-_transition_platform = transition(
- implementation = _transition_platform_impl,
- inputs = [],
- outputs = ["//command_line_option:platforms"],
-)
-
-
-def _platform_transition_binary_impl(ctx):
- # We need to forward the DefaultInfo provider from the underlying rule.
- # Unfortunately, we can't do this directly, because Bazel requires that the executable to run
- # is actually generated by this rule, so we need to symlink to it, and generate a synthetic
- # forwarding DefaultInfo.
-
- result = []
- binary = ctx.attr.binary[0]
-
- default_info = binary[DefaultInfo]
- files = default_info.files
- new_executable = None
- original_executable = default_info.files_to_run.executable
- runfiles = default_info.default_runfiles
-
- if not original_executable:
- fail("Cannot transition a 'binary' that is not executable")
-
- new_executable_name = ctx.attr.basename if ctx.attr.basename else original_executable.basename
-
- # In order for the symlink to have the same basename as the original
- # executable (important in the case of proto plugins), put it in a
- # subdirectory named after the label to prevent collisions.
- new_executable = ctx.actions.declare_file(paths.join(ctx.label.name, new_executable_name))
- ctx.actions.symlink(
- output = new_executable,
- target_file = original_executable,
- is_executable = True,
- )
- files = depset(direct = [new_executable], transitive = [files])
- runfiles = runfiles.merge(ctx.runfiles([new_executable]))
-
- result.append(
- DefaultInfo(
- files = files,
- runfiles = runfiles,
- executable = new_executable,
- ),
- )
-
- return result
-
-platform_transition_binary = rule(
- implementation = _platform_transition_binary_impl,
- attrs = {
- "basename": attr.string(),
- "binary": attr.label(allow_files = True, cfg = _transition_platform),
- "target_platform": attr.label(
- doc = "The target platform to transition the binary.",
- mandatory = True,
- ),
- "_allowlist_function_transition": attr.label(
- default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
- ),
- },
- executable = True,
- doc = "Transitions the binary to use the provided platform.",
-)
\ No newline at end of file
diff --git a/metropolis/node/build/earlydev.fsspec b/metropolis/node/build/earlydev.fsspec
deleted file mode 100644
index a7d2ea4..0000000
--- a/metropolis/node/build/earlydev.fsspec
+++ /dev/null
@@ -1,54 +0,0 @@
-# Critical /dev files which should be present as early as possible, ie. be baked
-# into filesystem images.
-
-# At least /dev/console and /dev/null are required to exist for Linux
-# to properly boot an init. Here we additionally include important device nodes
-# like /dev/kmsg and /dev/ptmx which might need to be available before a proper
-# device manager (ie. devtmpfs) is launched.
-special_file <
- path: "/dev/console"
- type: CHARACTER_DEV
- major: 5 minor: 1
- mode: 0600 uid: 0 gid: 0
->
-special_file <
- path: "/dev/ptmx"
- type: CHARACTER_DEV
- major: 5 minor: 2
- mode: 0644 uid: 0 gid: 0
->
-special_file <
- path: "/dev/null"
- type: CHARACTER_DEV
- major: 1 minor: 3
- mode: 0644 uid: 0 gid: 0
->
-special_file <
- path: "/dev/kmsg"
- type: CHARACTER_DEV
- major: 1 minor: 11
- mode: 0644 uid: 0 gid: 0
->
-
-
-# Metropolis core logs to /dev/ttyS{0,1} and /dev/tty0 by default, we want
-# these to also be present before devtmpfs is mounted so that minit can
-# log there, too.
-special_file <
- path: "/dev/tty0"
- type: CHARACTER_DEV
- major: 4 minor: 0
- mode: 0600 uid: 0 gid: 0
->
-special_file <
- path: "/dev/ttyS0"
- type: CHARACTER_DEV
- major: 4 minor: 64
- mode: 0660 uid: 0 gid: 0
->
-special_file <
- path: "/dev/ttyS1"
- type: CHARACTER_DEV
- major: 4 minor: 65
- mode: 0660 uid: 0 gid: 0
->
\ No newline at end of file
diff --git a/metropolis/node/build/efi.bzl b/metropolis/node/build/efi.bzl
deleted file mode 100644
index bf5ad26..0000000
--- a/metropolis/node/build/efi.bzl
+++ /dev/null
@@ -1,135 +0,0 @@
-"""Rules for generating EFI unified kernel images. These are EFI-bootable PE/COFF files containing a stub loader,
-a kernel, and optional commandline and initramfs in one file.
-See https://systemd.io/BOOT_LOADER_SPECIFICATION/#type-2-efi-unified-kernel-images for more information.
-"""
-
-load("//build/toolchain/llvm-efi:transition.bzl", "build_efi_transition")
-load("//metropolis/node/build:def.bzl", "VerityConfig")
-
-def _efi_unified_kernel_image_impl(ctx):
- # Find the dependency paths to be passed to mkpayload.
- deps = {
- "linux": ctx.file.kernel,
- "osrel": ctx.file.os_release,
- "splash": ctx.file.splash,
- "stub": ctx.file.stub,
- }
-
- # Since cmdline is a string attribute, put it into a file, then append
- # that file to deps.
- if ctx.attr.cmdline and ctx.attr.cmdline != "":
- cmdline = ctx.actions.declare_file("cmdline")
- ctx.actions.write(
- output = cmdline,
- content = ctx.attr.cmdline,
- )
- deps["cmdline"] = cmdline
-
- # Get the dm-verity target table from VerityConfig provider.
- if ctx.attr.verity:
- deps["rootfs_dm_table"] = ctx.attr.verity[VerityConfig].table
-
- # Format deps into command line arguments while keeping track of mkpayload
- # runtime inputs.
- args = []
- inputs = []
- for name, file in deps.items():
- if file:
- args.append("-{}={}".format(name, file.path))
- inputs.append(file)
-
- for file in ctx.files.initrd:
- args.append("-initrd={}".format(file.path))
- inputs.append(file)
-
- # Append the output parameter separately, as it doesn't belong with the
- # runtime inputs.
- image = ctx.actions.declare_file(ctx.attr.name + ".efi")
- args.append("-output={}".format(image.path))
-
- # Append the objcopy parameter separately, as it's not of File type, and
- # it does not constitute an input, since it's part of the toolchain.
- objcopy = ctx.toolchains["@bazel_tools//tools/cpp:toolchain_type"].cc.objcopy_executable
- args.append("-objcopy={}".format(objcopy))
-
- # Run mkpayload.
- ctx.actions.run(
- mnemonic = "GenEFIKernelImage",
- progress_message = "Generating EFI unified kernel image",
- inputs = inputs,
- outputs = [image],
- executable = ctx.file._mkpayload,
- arguments = args,
- )
-
- # Return the unified kernel image file.
- return [DefaultInfo(files = depset([image]), runfiles = ctx.runfiles(files = [image]))]
-
-efi_unified_kernel_image = rule(
- implementation = _efi_unified_kernel_image_impl,
- attrs = {
- "kernel": attr.label(
- doc = "The Linux kernel executable bzImage. Needs to have EFI handover and EFI stub enabled.",
- mandatory = True,
- allow_single_file = True,
- ),
- "cmdline": attr.string(
- doc = "The kernel commandline to be embedded.",
- ),
- "initrd": attr.label_list(
- doc = """
- List of payloads to concatenate and supply as the initrd parameter to Linux when it boots.
- The name stems from the time Linux booted from an initial ram disk (initrd), but it's now
- a catch-all for a bunch of different larger payload for early Linux initialization.
-
- In Linux 5.15 this can first contain an arbitrary amount of uncompressed cpio archives
- with directories being optional which is accessed by earlycpio. This is used for both
- early microcode loading and ACPI table overrides. This can then be followed by an arbitrary
- amount of compressed cpio archives (even with different compression methods) which will
- together make up the initramfs. The initramfs is only booted into if it contains either
- /init or whatever file is specified as init= in cmdline. Technically depending on kernel
- flags you might be able to supply an actual initrd, i.e. an image of a disk loaded into
- RAM, but that has been deprecated for nearly 2 decades and should really not be used.
-
- For kernels designed to run on physical machines this should at least contain microcode,
- optionally followed by a compressed initramfs. For kernels only used in virtualized
- setups the microcode can be left out and if no initramfs is needed this option can
- be omitted completely.
- """,
- allow_files = True,
- ),
- "os_release": attr.label(
- doc = """
- The os-release file identifying the operating system.
- See https://www.freedesktop.org/software/systemd/man/os-release.html for format.
- """,
- allow_single_file = True,
- ),
- "splash": attr.label(
- doc = "An image in BMP format which will be displayed as a splash screen until the kernel takes over.",
- allow_single_file = True,
- ),
- "stub": attr.label(
- doc = "The stub executable itself as a PE/COFF executable.",
- default = "@efistub//:efistub",
- allow_single_file = True,
- executable = True,
- cfg = build_efi_transition,
- ),
- "verity": attr.label(
- doc = "The DeviceMapper Verity rootfs target table.",
- allow_single_file = True,
- providers = [DefaultInfo, VerityConfig],
- ),
- "_mkpayload": attr.label(
- doc = "The mkpayload executable.",
- default = "//metropolis/node/build/mkpayload",
- allow_single_file = True,
- executable = True,
- cfg = "exec",
- ),
- },
- toolchains = [
- "@bazel_tools//tools/cpp:toolchain_type"
- ],
-)
diff --git a/metropolis/node/build/fsspec/BUILD.bazel b/metropolis/node/build/fsspec/BUILD.bazel
deleted file mode 100644
index eeddda7..0000000
--- a/metropolis/node/build/fsspec/BUILD.bazel
+++ /dev/null
@@ -1,25 +0,0 @@
-load("@rules_proto//proto:defs.bzl", "proto_library")
-load("@io_bazel_rules_go//go:def.bzl", "go_library")
-load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
-
-proto_library(
- name = "spec_proto",
- srcs = ["spec.proto"],
- visibility = ["//visibility:public"],
-)
-
-go_library(
- name = "fsspec",
- srcs = ["utils.go"],
- embed = [":fsspec_go_proto"],
- importpath = "source.monogon.dev/metropolis/node/build/fsspec",
- visibility = ["//visibility:public"],
- deps = ["@org_golang_google_protobuf//encoding/prototext"],
-)
-
-go_proto_library(
- name = "fsspec_go_proto",
- importpath = "source.monogon.dev/metropolis/node/build/fsspec",
- proto = ":spec_proto",
- visibility = ["//visibility:public"],
-)
diff --git a/metropolis/node/build/fsspec/spec.proto b/metropolis/node/build/fsspec/spec.proto
deleted file mode 100644
index 712de1c..0000000
--- a/metropolis/node/build/fsspec/spec.proto
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2020 The Monogon Project Authors.
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto3";
-
-package metropolis.node.build.fsspec;
-option go_package = "source.monogon.dev/metropolis/node/build/fsspec";
-
-// FSSpec is the spec from which a filesystem is generated. It consists of files, directories and symbolic
-// links. Directories are also automatically inferred when required for the placement of files or symbolic
-// links. Inferred directories always have uid 0, gid 0 and permissions 0555. This can be overridden by
-// explicitly specifying a directory at a given path.
-message FSSpec {
- repeated File file = 1;
- repeated Directory directory = 2;
- repeated SymbolicLink symbolic_link = 3;
- repeated SpecialFile special_file = 4;
-}
-
-// For internal use only. Represents all supported inodes in a oneof.
-message Inode {
- oneof type {
- File file = 1;
- Directory directory = 2;
- SymbolicLink symbolic_link = 3;
- SpecialFile special_file = 4;
- }
-}
-
-message File {
- // The path where the file ends up in the filesystem.
- string path = 1;
- // The path on the host filesystem where the file contents should be taken from.
- string source_path = 2;
- // Unix permission bits
- uint32 mode = 3;
- // Owner uid
- uint32 uid = 4;
- // Owner gid
- uint32 gid = 5;
-}
-
-message Directory {
- // The path where the directory ends up in the filesystem.
- string path = 1;
- // Unix permission bits
- uint32 mode = 2;
- // Owner uid
- uint32 uid = 3;
- // Owner gid
- uint32 gid = 4;
-}
-
-message SymbolicLink {
- // The path where the symbolic link ends up in the filesystem.
- string path = 1;
- // The path to which the symbolic link resolves to.
- string target_path = 2;
-}
-
-message SpecialFile {
- // The path where the special file ends up in the filesystem.
- string path = 1;
-
- enum Type {
- CHARACTER_DEV = 0;
- BLOCK_DEV = 1;
- FIFO = 2;
- }
-
- // Type of special file.
- Type type = 2;
-
- // The major device number of the special file.
- uint32 major = 3;
- // The minor number of the special file. Ignored for FIFO-type special files.
- uint32 minor = 4;
-
- // Unix permission bits
- uint32 mode = 5;
- // Owner uid
- uint32 uid = 6;
- // Owner gid
- uint32 gid = 7;
-}
\ No newline at end of file
diff --git a/metropolis/node/build/fsspec/utils.go b/metropolis/node/build/fsspec/utils.go
deleted file mode 100644
index f5a45e3..0000000
--- a/metropolis/node/build/fsspec/utils.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package fsspec
-
-import (
- "fmt"
- "os"
-
- "google.golang.org/protobuf/encoding/prototext"
-)
-
-// ReadMergeSpecs reads FSSpecs from all files in paths and merges them into
-// a single FSSpec.
-func ReadMergeSpecs(paths []string) (*FSSpec, error) {
- var mergedSpec FSSpec
- for _, p := range paths {
- specRaw, err := os.ReadFile(p)
- if err != nil {
- return nil, fmt.Errorf("failed to open spec: %w", err)
- }
-
- var spec FSSpec
- if err := prototext.Unmarshal(specRaw, &spec); err != nil {
- return nil, fmt.Errorf("failed to parse spec %q: %w", p, err)
- }
- mergedSpec.File = append(mergedSpec.File, spec.File...)
- mergedSpec.Directory = append(mergedSpec.Directory, spec.Directory...)
- mergedSpec.SymbolicLink = append(mergedSpec.SymbolicLink, spec.SymbolicLink...)
- mergedSpec.SpecialFile = append(mergedSpec.SpecialFile, spec.SpecialFile...)
- }
- return &mergedSpec, nil
-}
diff --git a/metropolis/node/build/fwprune/BUILD.bazel b/metropolis/node/build/fwprune/BUILD.bazel
deleted file mode 100644
index e29ac7e..0000000
--- a/metropolis/node/build/fwprune/BUILD.bazel
+++ /dev/null
@@ -1,20 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
-
-go_library(
- name = "fwprune_lib",
- srcs = ["main.go"],
- importpath = "source.monogon.dev/metropolis/node/build/fwprune",
- visibility = ["//visibility:private"],
- deps = [
- "//metropolis/node/build/fsspec",
- "//osbase/kmod",
- "@org_golang_google_protobuf//encoding/prototext",
- "@org_golang_google_protobuf//proto",
- ],
-)
-
-go_binary(
- name = "fwprune",
- embed = [":fwprune_lib"],
- visibility = ["//visibility:public"],
-)
diff --git a/metropolis/node/build/fwprune/def.bzl b/metropolis/node/build/fwprune/def.bzl
deleted file mode 100644
index 154009e..0000000
--- a/metropolis/node/build/fwprune/def.bzl
+++ /dev/null
@@ -1,76 +0,0 @@
-load("//metropolis/node/build:def.bzl", "FSSpecInfo")
-
-def _fsspec_linux_firmware(ctx):
- fsspec_out = ctx.actions.declare_file(ctx.label.name + ".prototxt")
-
- fwlist = ctx.actions.declare_file(ctx.label.name + "-fwlist.txt")
- ctx.actions.write(
- output = fwlist,
- content = "\n".join([f.path for f in ctx.files.firmware_files]),
- )
-
- modinfo = ctx.attr.kernel[OutputGroupInfo].modinfo.to_list()[0]
- modules = ctx.attr.kernel[OutputGroupInfo].modules.to_list()[0]
-
- meta_out = ctx.actions.declare_file(ctx.label.name + "-meta.pb")
-
- ctx.actions.run(
- outputs = [fsspec_out, meta_out],
- inputs = [fwlist, modinfo, modules, ctx.file.metadata] + ctx.files.firmware_files,
- tools = [ctx.executable._fwprune],
- executable = ctx.executable._fwprune,
- arguments = [
- "-modinfo",
- modinfo.path,
- "-modules",
- modules.path,
- "-firmware-file-list",
- fwlist.path,
- "-firmware-whence",
- ctx.file.metadata.path,
- "-out-meta",
- meta_out.path,
- "-out-fsspec",
- fsspec_out.path,
- ],
- )
-
- return [DefaultInfo(files = depset([fsspec_out])), FSSpecInfo(spec = fsspec_out, referenced = ctx.files.firmware_files + [modules, meta_out])]
-
-fsspec_linux_firmware = rule(
- implementation = _fsspec_linux_firmware,
- doc = """
- Generates a partial filesystem spec containing all firmware files required by a given kernel at the
- default firmware load path (/lib/firmware).
- """,
- attrs = {
- "firmware_files": attr.label_list(
- mandatory = True,
- allow_files = True,
- doc = """
- List of firmware files. Generally at least a filegroup of the linux-firmware repository should
- be in here.
- """,
- ),
- "metadata": attr.label(
- mandatory = True,
- allow_single_file = True,
- doc = """
- The metadata file for the Linux firmware. Currently this is the WHENCE file at the root of the
- linux-firmware repository. Used for resolving additional links.
- """,
- ),
- "kernel": attr.label(
- doc = """
- Kernel for which firmware should be selected. Needs to have a modinfo OutputGroup.
- """,
- ),
-
- # Tool
- "_fwprune": attr.label(
- default = Label("//metropolis/node/build/fwprune"),
- executable = True,
- cfg = "exec",
- ),
- },
-)
diff --git a/metropolis/node/build/fwprune/main.go b/metropolis/node/build/fwprune/main.go
deleted file mode 100644
index e76e5d0..0000000
--- a/metropolis/node/build/fwprune/main.go
+++ /dev/null
@@ -1,218 +0,0 @@
-// fwprune is a buildsystem utility that filters linux-firmware repository
-// contents to include only files required by the built-in kernel modules,
-// that are specified in modules.builtin.modinfo.
-// (see: https://www.kernel.org/doc/Documentation/kbuild/kbuild.txt)
-package main
-
-import (
- "debug/elf"
- "flag"
- "io/fs"
- "log"
- "os"
- "path"
- "path/filepath"
- "regexp"
- "sort"
- "strings"
-
- "google.golang.org/protobuf/encoding/prototext"
- "google.golang.org/protobuf/proto"
-
- "source.monogon.dev/metropolis/node/build/fsspec"
- "source.monogon.dev/osbase/kmod"
-)
-
-// linkRegexp parses the Link: lines in the WHENCE file. This does not have
-// an official grammar, the regexp has been written in an approximation of
-// the original parsing algorithm at @linux-firmware//:copy_firmware.sh.
-var linkRegexp = regexp.MustCompile(`(?m:^Link:\s*([^\s]+)\s+->\s+([^\s]+)\s*$)`)
-
-var (
- modinfoPath = flag.String("modinfo", "", "Path to the modules.builtin.modinfo file built with the kernel")
- modulesPath = flag.String("modules", "", "Path to the directory containing the dynamically loaded kernel modules (.ko files)")
- firmwareListPath = flag.String("firmware-file-list", "", "Path to a file containing a newline-separated list of paths to firmware files")
- whenceFilePath = flag.String("firmware-whence", "", "Path to the linux-firmware WHENCE file containing aliases for firmware files")
- outMetaPath = flag.String("out-meta", "", "Path where the resulting module metadata protobuf file should be created")
- outFSSpecPath = flag.String("out-fsspec", "", "Path where the resulting fsspec should be created")
-)
-
-func main() {
- flag.Parse()
- if *modinfoPath == "" || *modulesPath == "" || *firmwareListPath == "" ||
- *whenceFilePath == "" || *outMetaPath == "" || *outFSSpecPath == "" {
- log.Fatal("all flags are required and need to be provided")
- }
-
- allFirmwareData, err := os.ReadFile(*firmwareListPath)
- if err != nil {
- log.Fatalf("Failed to read firmware source list: %v", err)
- }
- allFirmwarePaths := strings.Split(string(allFirmwareData), "\n")
-
- // Create a look-up table of all possible suffixes to their full paths as
- // this is much faster at O(n) than calling strings.HasSuffix for every
- // possible combination which is O(n^2).
- // For example a build output at out/a/b/c.bin will be entered into
- // the suffix LUT as build as out/a/b/c.bin, a/b/c.bin, b/c.bin and c.bin.
- // If the firmware then requests b/c.bin, the output path is contained in
- // the suffix LUT.
- suffixLUT := make(map[string]string)
- for _, firmwarePath := range allFirmwarePaths {
- pathParts := strings.Split(firmwarePath, string(os.PathSeparator))
- for i := range pathParts {
- suffixLUT[path.Join(pathParts[i:]...)] = firmwarePath
- }
- }
-
- // The linux-firmware repo contains a WHENCE file which contains (among
- // other information) aliases for firmware which should be symlinked.
- // Open this file and create a map of aliases in it.
- linkMap := make(map[string]string)
- metadata, err := os.ReadFile(*whenceFilePath)
- if err != nil {
- log.Fatalf("Failed to read metadata file: %v", err)
- }
- linksRaw := linkRegexp.FindAllStringSubmatch(string(metadata), -1)
- for _, link := range linksRaw {
- // For links we know the exact path referenced by kernel drives so
- // a suffix LUT is unnecessary.
- linkMap[link[1]] = link[2]
- }
-
- // Collect module metadata (modinfo) from both built-in modules via the
- // kbuild-generated metadata file as well as from the loadable modules by
- // walking them.
- var files []*fsspec.File
- var symlinks []*fsspec.SymbolicLink
-
- mi, err := os.Open(*modinfoPath)
- if err != nil {
- log.Fatalf("While reading modinfo: %v", err)
- }
- modMeta, err := kmod.GetBuiltinModulesInfo(mi)
- if err != nil {
- log.Fatalf("Failed to read modules modinfo data: %v", err)
- }
-
- err = filepath.WalkDir(*modulesPath, func(p string, d fs.DirEntry, err error) error {
- if err != nil {
- log.Fatal(err)
- }
- if d.IsDir() {
- return nil
- }
- mod, err := elf.Open(p)
- if err != nil {
- log.Fatal(err)
- }
- defer mod.Close()
- out, err := kmod.GetModuleInfo(mod)
- if err != nil {
- log.Fatal(err)
- }
- relPath, err := filepath.Rel(*modulesPath, p)
- if err != nil {
- return err
- }
- // Add path information for MakeMetaFromModuleInfo.
- out["path"] = []string{relPath}
- modMeta = append(modMeta, out)
- files = append(files, &fsspec.File{
- Path: path.Join("/lib/modules", relPath),
- SourcePath: filepath.Join(*modulesPath, relPath),
- Mode: 0555,
- })
- return nil
- })
- if err != nil {
- log.Fatalf("Error walking modules: %v", err)
- }
-
- // Generate loading metadata from all known modules.
- meta, err := kmod.MakeMetaFromModuleInfo(modMeta)
- if err != nil {
- log.Fatal(err)
- }
- metaRaw, err := proto.Marshal(meta)
- if err != nil {
- log.Fatal(err)
- }
- if err := os.WriteFile(*outMetaPath, metaRaw, 0640); err != nil {
- log.Fatal(err)
- }
- files = append(files, &fsspec.File{
- Path: "/lib/modules/meta.pb",
- SourcePath: *outMetaPath,
- Mode: 0444,
- })
-
- // Create set of all firmware paths required by modules
- fwset := make(map[string]bool)
- for _, m := range modMeta {
- if len(m["path"]) == 0 && len(m.Firmware()) > 0 {
- log.Fatalf("Module %v is built-in, but requires firmware. Linux does not support this in all configurations.", m.Name())
- }
- for _, fw := range m.Firmware() {
- fwset[fw] = true
- }
- }
-
- // Convert set to list and sort for determinism
- fwp := make([]string, 0, len(fwset))
- for p := range fwset {
- fwp = append(fwp, p)
- }
- sort.Strings(fwp)
-
- // This function is called for every requested firmware file and adds and
- // resolves symlinks until it finds the target file and adds that too.
- populatedPaths := make(map[string]bool)
- var chaseReference func(string)
- chaseReference = func(p string) {
- if populatedPaths[p] {
- // Bail if path is already populated. Because of the DAG-like
- // property of links in filesystems everything transitively pointed
- // to by anything at this path has already been included.
- return
- }
- placedPath := path.Join("/lib/firmware", p)
- if linkTarget := linkMap[p]; linkTarget != "" {
- symlinks = append(symlinks, &fsspec.SymbolicLink{
- Path: placedPath,
- TargetPath: linkTarget,
- })
- populatedPaths[p] = true
- // Symlinks are relative to their place, resolve them to be relative
- // to the firmware root directory.
- chaseReference(path.Join(path.Dir(p), linkTarget))
- return
- }
- sourcePath := suffixLUT[p]
- if sourcePath == "" {
- // This should not be fatal as sometimes linux-firmware cannot
- // ship all firmware usable by the kernel for mostly legal reasons.
- log.Printf("WARNING: Requested firmware %q not found", p)
- return
- }
- files = append(files, &fsspec.File{
- Path: path.Join("/lib/firmware", p),
- Mode: 0444,
- SourcePath: sourcePath,
- })
- populatedPaths[p] = true
- }
-
- for _, p := range fwp {
- chaseReference(p)
- }
- // Format output in a both human- and machine-readable form
- marshalOpts := prototext.MarshalOptions{Multiline: true, Indent: " "}
- fsspecRaw, err := marshalOpts.Marshal(&fsspec.FSSpec{File: files, SymbolicLink: symlinks})
- if err != nil {
- log.Fatalf("failed to marshal fsspec: %v", err)
- }
- if err := os.WriteFile(*outFSSpecPath, fsspecRaw, 0644); err != nil {
- log.Fatalf("failed writing output: %v", err)
- }
-}
diff --git a/metropolis/node/build/genosrelease/BUILD.bazel b/metropolis/node/build/genosrelease/BUILD.bazel
deleted file mode 100644
index 5ac09d5..0000000
--- a/metropolis/node/build/genosrelease/BUILD.bazel
+++ /dev/null
@@ -1,18 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
-
-go_library(
- name = "genosrelease_lib",
- srcs = ["main.go"],
- importpath = "source.monogon.dev/metropolis/node/build/genosrelease",
- visibility = ["//visibility:private"],
- deps = ["@com_github_joho_godotenv//:godotenv"],
-)
-
-go_binary(
- name = "genosrelease",
- embed = [":genosrelease_lib"],
- visibility = [
- "//metropolis/installer:__subpackages__",
- "//metropolis/node:__subpackages__",
- ],
-)
diff --git a/metropolis/node/build/genosrelease/defs.bzl b/metropolis/node/build/genosrelease/defs.bzl
deleted file mode 100644
index 61ce9e4..0000000
--- a/metropolis/node/build/genosrelease/defs.bzl
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright 2020 The Monogon Project Authors.
-#
-# SPDX-License-Identifier: Apache-2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-def _os_release_impl(ctx):
- ctx.actions.run(
- mnemonic = "GenOSRelease",
- progress_message = "Generating os-release",
- inputs = [ctx.info_file],
- outputs = [ctx.outputs.out],
- executable = ctx.executable._genosrelease,
- arguments = [
- "-status_file",
- ctx.info_file.path,
- "-out_file",
- ctx.outputs.out.path,
- "-stamp_var",
- ctx.attr.stamp_var,
- "-name",
- ctx.attr.os_name,
- "-id",
- ctx.attr.os_id,
- ],
- )
-
-os_release = rule(
- implementation = _os_release_impl,
- attrs = {
- "os_name": attr.string(mandatory = True),
- "os_id": attr.string(mandatory = True),
- "stamp_var": attr.string(mandatory = True),
- "_genosrelease": attr.label(
- default = Label("//metropolis/node/build/genosrelease"),
- cfg = "host",
- executable = True,
- allow_files = True,
- ),
- },
- outputs = {
- "out": "os-release",
- },
-)
diff --git a/metropolis/node/build/genosrelease/main.go b/metropolis/node/build/genosrelease/main.go
deleted file mode 100644
index adb8202..0000000
--- a/metropolis/node/build/genosrelease/main.go
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2020 The Monogon Project Authors.
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// genosrelease provides rudimentary support to generate os-release files
-// following the freedesktop spec from arguments and stamping
-//
-// https://www.freedesktop.org/software/systemd/man/os-release.html
-package main
-
-import (
- "flag"
- "fmt"
- "os"
- "strings"
-
- "github.com/joho/godotenv"
-)
-
-var (
- flagStatusFile = flag.String("status_file", "", "path to bazel workspace status file")
- flagOutFile = flag.String("out_file", "os-release", "path to os-release output file")
- flagStampVar = flag.String("stamp_var", "", "variable to use as version from the workspace status file")
- flagName = flag.String("name", "", "name parameter (see freedesktop spec)")
- flagID = flag.String("id", "", "id parameter (see freedesktop spec)")
-)
-
-func main() {
- flag.Parse()
- statusFileContent, err := os.ReadFile(*flagStatusFile)
- if err != nil {
- fmt.Printf("Failed to open bazel workspace status file: %v\n", err)
- os.Exit(1)
- }
- statusVars := make(map[string]string)
- for _, line := range strings.Split(string(statusFileContent), "\n") {
- line = strings.TrimSpace(line)
- parts := strings.Fields(line)
- if len(parts) != 2 {
- continue
- }
- statusVars[parts[0]] = parts[1]
- }
-
- version, ok := statusVars[*flagStampVar]
- if !ok {
- fmt.Printf("%v key not set in bazel workspace status file\n", *flagStampVar)
- os.Exit(1)
- }
- // As specified by https://www.freedesktop.org/software/systemd/man/os-release.html
- osReleaseVars := map[string]string{
- "NAME": *flagName,
- "ID": *flagID,
- "VERSION": version,
- "VERSION_ID": version,
- "PRETTY_NAME": *flagName + " " + version,
- }
- osReleaseContent, err := godotenv.Marshal(osReleaseVars)
- if err != nil {
- fmt.Printf("Failed to encode os-release file: %v\n", err)
- os.Exit(1)
- }
- if err := os.WriteFile(*flagOutFile, []byte(osReleaseContent), 0644); err != nil {
- fmt.Printf("Failed to write os-release file: %v\n", err)
- os.Exit(1)
- }
-}
diff --git a/metropolis/node/build/kconfig-patcher/BUILD.bazel b/metropolis/node/build/kconfig-patcher/BUILD.bazel
deleted file mode 100644
index 278db21..0000000
--- a/metropolis/node/build/kconfig-patcher/BUILD.bazel
+++ /dev/null
@@ -1,23 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
-
-go_library(
- name = "kconfig-patcher_lib",
- srcs = ["main.go"],
- importpath = "source.monogon.dev/metropolis/node/build/kconfig-patcher",
- visibility = ["//visibility:private"],
-)
-
-go_binary(
- name = "kconfig-patcher",
- embed = [":kconfig-patcher_lib"],
- visibility = [
- "//metropolis/node:__pkg__",
- "//osbase/test/ktest:__pkg__",
- ],
-)
-
-go_test(
- name = "kconfig-patcher_test",
- srcs = ["main_test.go"],
- embed = [":kconfig-patcher_lib"],
-)
diff --git a/metropolis/node/build/kconfig-patcher/kconfig-patcher.bzl b/metropolis/node/build/kconfig-patcher/kconfig-patcher.bzl
deleted file mode 100644
index 337642e..0000000
--- a/metropolis/node/build/kconfig-patcher/kconfig-patcher.bzl
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright 2020 The Monogon Project Authors.
-#
-# SPDX-License-Identifier: Apache-2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Override configs in a Linux kernel Kconfig
-"""
-
-def kconfig_patch(name, src, out, override_configs, **kwargs):
- native.genrule(
- name = name,
- srcs = [src],
- outs = [out],
- tools = [
- "//metropolis/node/build/kconfig-patcher",
- ],
- cmd = """
- $(location //metropolis/node/build/kconfig-patcher) \
- -in $< -out $@ '%s'
- """ % struct(overrides = override_configs).to_json(),
- **kwargs
- )
diff --git a/metropolis/node/build/kconfig-patcher/main.go b/metropolis/node/build/kconfig-patcher/main.go
deleted file mode 100644
index 1b5f24f..0000000
--- a/metropolis/node/build/kconfig-patcher/main.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2020 The Monogon Project Authors.
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "bufio"
- "encoding/json"
- "flag"
- "fmt"
- "io"
- "os"
- "strings"
-)
-
-var (
- inPath = flag.String("in", "", "Path to input Kconfig")
- outPath = flag.String("out", "", "Path to output Kconfig")
-)
-
-func main() {
- flag.Parse()
- if *inPath == "" || *outPath == "" {
- flag.PrintDefaults()
- os.Exit(2)
- }
- inFile, err := os.Open(*inPath)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Failed to open input Kconfig: %v\n", err)
- os.Exit(1)
- }
- outFile, err := os.Create(*outPath)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Failed to create output Kconfig: %v\n", err)
- os.Exit(1)
- }
- var config struct {
- Overrides map[string]string `json:"overrides"`
- }
- if err := json.Unmarshal([]byte(flag.Arg(0)), &config); err != nil {
- fmt.Fprintf(os.Stderr, "Failed to parse overrides: %v\n", err)
- os.Exit(1)
- }
- err = patchKconfig(inFile, outFile, config.Overrides)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Failed to patch: %v\n", err)
- os.Exit(1)
- }
-}
-
-func patchKconfig(inFile io.Reader, outFile io.Writer, overrides map[string]string) error {
- scanner := bufio.NewScanner(inFile)
- for scanner.Scan() {
- if scanner.Err() != nil {
- return scanner.Err()
- }
- line := scanner.Text()
- cleanLine := strings.TrimSpace(line)
- if strings.HasPrefix(cleanLine, "#") || cleanLine == "" {
- // Pass through comments and empty lines
- fmt.Fprintln(outFile, line)
- } else {
- // Line contains a configuration option
- parts := strings.SplitN(line, "=", 2)
- keyName := parts[0]
- if overrideVal, ok := overrides[strings.TrimSpace(keyName)]; ok {
- // Override it
- if overrideVal == "" {
- fmt.Fprintf(outFile, "# %v is not set\n", keyName)
- } else {
- fmt.Fprintf(outFile, "%v=%v\n", keyName, overrideVal)
- }
- delete(overrides, keyName)
- } else {
- // Pass through unchanged
- fmt.Fprintln(outFile, line)
- }
- }
- }
- // Process left over overrides
- for key, val := range overrides {
- fmt.Fprintf(outFile, "%v=%v\n", key, val)
- }
- return nil
-}
diff --git a/metropolis/node/build/kconfig-patcher/main_test.go b/metropolis/node/build/kconfig-patcher/main_test.go
deleted file mode 100644
index 11c7d84..0000000
--- a/metropolis/node/build/kconfig-patcher/main_test.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2020 The Monogon Project Authors.
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "bytes"
- "strings"
- "testing"
-)
-
-func Test_patchKconfig(t *testing.T) {
- type args struct {
- inFile string
- overrides map[string]string
- }
- tests := []struct {
- name string
- args args
- wantOutFile string
- wantErr bool
- }{
- {
- "passthroughExtend",
- args{inFile: "# TEST=y\n\n", overrides: map[string]string{"TEST": "n"}},
- "# TEST=y\n\nTEST=n\n",
- false,
- },
- {
- "patch",
- args{inFile: "TEST=y\nTEST_NO=n\n", overrides: map[string]string{"TEST": "n"}},
- "TEST=n\nTEST_NO=n\n",
- false,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- outFile := &bytes.Buffer{}
- if err := patchKconfig(strings.NewReader(tt.args.inFile), outFile, tt.args.overrides); (err != nil) != tt.wantErr {
- t.Errorf("patchKconfig() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if gotOutFile := outFile.String(); gotOutFile != tt.wantOutFile {
- t.Errorf("patchKconfig() = %v, want %v", gotOutFile, tt.wantOutFile)
- }
- })
- }
-}
diff --git a/metropolis/node/build/mkcpio/BUILD.bazel b/metropolis/node/build/mkcpio/BUILD.bazel
deleted file mode 100644
index 3ea98ae..0000000
--- a/metropolis/node/build/mkcpio/BUILD.bazel
+++ /dev/null
@@ -1,20 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
-
-go_library(
- name = "mkcpio_lib",
- srcs = ["main.go"],
- importpath = "source.monogon.dev/metropolis/node/build/mkcpio",
- visibility = ["//visibility:private"],
- deps = [
- "//metropolis/node/build/fsspec",
- "@com_github_cavaliergopher_cpio//:cpio",
- "@com_github_klauspost_compress//zstd",
- "@org_golang_x_sys//unix",
- ],
-)
-
-go_binary(
- name = "mkcpio",
- embed = [":mkcpio_lib"],
- visibility = ["//visibility:public"],
-)
diff --git a/metropolis/node/build/mkcpio/main.go b/metropolis/node/build/mkcpio/main.go
deleted file mode 100644
index b8f99b9..0000000
--- a/metropolis/node/build/mkcpio/main.go
+++ /dev/null
@@ -1,218 +0,0 @@
-package main
-
-import (
- "flag"
- "io"
- "log"
- "os"
- "path"
- "sort"
- "strings"
-
- "github.com/cavaliergopher/cpio"
- "github.com/klauspost/compress/zstd"
- "golang.org/x/sys/unix"
-
- "source.monogon.dev/metropolis/node/build/fsspec"
-)
-
-var (
- outPath = flag.String("out", "", "Output file path")
-)
-
-type placeEnum int
-
-const (
- // placeNone implies that currently nothing is placed at that path.
- // Can be overridden by everything.
- placeNone placeEnum = 0
- // placeDirImplicit means that there is currently a implied directory
- // at the given path. It can be overridden by (and only by) an explicit
- // directory.
- placeDirImplicit placeEnum = 1
- // placeDirExplicit means that there is an explicit (i.e. specified by
- // the FSSpec) directory at the given path. Nothing else can override
- // this.
- placeDirExplicit placeEnum = 2
- // placeNonDir means that there is a file-type resource (i.e a file, symlink
- // or special_file) at the given path. Nothing else can override this.
- placeNonDir placeEnum = 3
-)
-
-// place represents the state a given canonical path is in during metadata
-// construction. Its zero value is { State: placeNone, Inode: nil }.
-type place struct {
- State placeEnum
- // Inode contains one of the types inside an FSSpec (e.g. *fsspec.File)
- Inode interface{}
-}
-
-// Usage: -out <out-path.cpio.zst> fsspec-path...
-func main() {
- flag.Parse()
- outFile, err := os.Create(*outPath)
- if err != nil {
- log.Fatalf("Failed to open CPIO output file: %v", err)
- }
- defer outFile.Close()
- compressedOut, err := zstd.NewWriter(outFile)
- if err != nil {
- log.Fatalf("While initializing zstd writer: %v", err)
- }
- defer compressedOut.Close()
- cpioWriter := cpio.NewWriter(compressedOut)
- defer cpioWriter.Close()
-
- spec, err := fsspec.ReadMergeSpecs(flag.Args())
- if err != nil {
- log.Fatalf("failed to load specs: %v", err)
- }
-
- // Map of paths to metadata for validation & implicit directory injection
- places := make(map[string]place)
-
- // The idea behind this machinery is that we try to place all files and
- // directories into a map while creating the required parent directories
- // on-the-fly as implicit directories. Overriding an implicit directory
- // with an explicit one is allowed thus the actual order in which this
- // structure is created does not matter. All non-directories cannot be
- // overridden anyways so their insertion order does not matter.
- // This also has the job of validating the FSSpec structure, ensuring that
- // there are no duplicate paths and that there is nothing placed below a
- // non-directory.
- var placeInode func(p string, isDir bool, inode interface{})
- placeInode = func(p string, isDir bool, inode interface{}) {
- cleanPath := path.Clean(p)
- if !isDir {
- if places[cleanPath].State != placeNone {
- log.Fatalf("Invalid FSSpec: Duplicate Inode at %q", cleanPath)
- }
- places[cleanPath] = place{
- State: placeNonDir,
- Inode: inode,
- }
- } else {
- switch places[cleanPath].State {
- case placeNone:
- if inode != nil {
- places[cleanPath] = place{
- State: placeDirExplicit,
- Inode: inode,
- }
- } else {
- places[cleanPath] = place{
- State: placeDirImplicit,
- Inode: &fsspec.Directory{Path: cleanPath, Mode: 0555},
- }
- }
- case placeDirImplicit:
- if inode != nil {
- places[cleanPath] = place{
- State: placeDirExplicit,
- Inode: inode,
- }
- }
- case placeDirExplicit:
- if inode != nil {
- log.Fatalf("Invalid FSSpec: Conflicting explicit directories at %v", cleanPath)
- }
- case placeNonDir:
- log.Fatalf("Invalid FSSpec: Trying to place inode below non-directory at #{cleanPath}")
- default:
- panic("unhandled placeEnum value")
- }
- }
- parentPath, _ := path.Split(p)
- parentPath = path.Clean(parentPath)
- if parentPath == "/" || parentPath == p {
- return
- }
- placeInode(parentPath, true, nil)
- }
- for _, d := range spec.Directory {
- placeInode(d.Path, true, d)
- }
- for _, f := range spec.File {
- placeInode(f.Path, false, f)
- }
- for _, s := range spec.SymbolicLink {
- placeInode(s.Path, false, s)
- }
- for _, s := range spec.SpecialFile {
- placeInode(s.Path, false, s)
- }
-
- var writeOrder []string
- for path := range places {
- writeOrder = append(writeOrder, path)
- }
- // Sorting a list of normalized paths representing a tree gives us Depth-
- // first search (DFS) order which is the correct order for writing archives.
- // This also makes the output reproducible.
- sort.Strings(writeOrder)
-
- for _, path := range writeOrder {
- place := places[path]
- switch i := place.Inode.(type) {
- case *fsspec.File:
- inF, err := os.Open(i.SourcePath)
- if err != nil {
- log.Fatalf("Failed to open source path for file %q: %v", i.Path, err)
- }
- inFStat, err := inF.Stat()
- if err != nil {
- log.Fatalf("Failed to stat source path for file %q: %v", i.Path, err)
- }
- if err := cpioWriter.WriteHeader(&cpio.Header{
- Mode: cpio.FileMode(i.Mode),
- Name: strings.TrimPrefix(i.Path, "/"),
- Size: inFStat.Size(),
- }); err != nil {
- log.Fatalf("Failed to write cpio header for file %q: %v", i.Path, err)
- }
- if n, err := io.Copy(cpioWriter, inF); err != nil || n != inFStat.Size() {
- log.Fatalf("Failed to copy file %q into cpio: %v", i.SourcePath, err)
- }
- inF.Close()
- case *fsspec.Directory:
- if err := cpioWriter.WriteHeader(&cpio.Header{
- Mode: cpio.FileMode(i.Mode) | cpio.TypeDir,
- Name: strings.TrimPrefix(i.Path, "/"),
- }); err != nil {
- log.Fatalf("Failed to write cpio header for directory %q: %v", i.Path, err)
- }
- case *fsspec.SymbolicLink:
- if err := cpioWriter.WriteHeader(&cpio.Header{
- // Symlinks are 0777 by definition (from man 7 symlink on Linux)
- Mode: 0777 | cpio.TypeSymlink,
- Name: strings.TrimPrefix(i.Path, "/"),
- Size: int64(len(i.TargetPath)),
- }); err != nil {
- log.Fatalf("Failed to write cpio header for symlink %q: %v", i.Path, err)
- }
- if _, err := cpioWriter.Write([]byte(i.TargetPath)); err != nil {
- log.Fatalf("Failed to write cpio symlink %q: %v", i.Path, err)
- }
- case *fsspec.SpecialFile:
- mode := cpio.FileMode(i.Mode)
- switch i.Type {
- case fsspec.SpecialFile_CHARACTER_DEV:
- mode |= cpio.TypeChar
- case fsspec.SpecialFile_BLOCK_DEV:
- mode |= cpio.TypeBlock
- case fsspec.SpecialFile_FIFO:
- mode |= cpio.TypeFifo
- }
-
- if err := cpioWriter.WriteHeader(&cpio.Header{
- Mode: mode,
- Name: strings.TrimPrefix(i.Path, "/"),
- DeviceID: int(unix.Mkdev(i.Major, i.Minor)),
- }); err != nil {
- log.Fatalf("Failed to write CPIO header for special file %q: %v", i.Path, err)
- }
- default:
- panic("inode type not handled")
- }
- }
-}
diff --git a/metropolis/node/build/mkerofs/BUILD.bazel b/metropolis/node/build/mkerofs/BUILD.bazel
deleted file mode 100644
index 0befb4c..0000000
--- a/metropolis/node/build/mkerofs/BUILD.bazel
+++ /dev/null
@@ -1,18 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
-
-go_library(
- name = "mkerofs_lib",
- srcs = ["main.go"],
- importpath = "source.monogon.dev/metropolis/node/build/mkerofs",
- visibility = ["//visibility:public"],
- deps = [
- "//metropolis/node/build/fsspec",
- "//osbase/erofs",
- ],
-)
-
-go_binary(
- name = "mkerofs",
- embed = [":mkerofs_lib"],
- visibility = ["//visibility:public"],
-)
diff --git a/metropolis/node/build/mkerofs/main.go b/metropolis/node/build/mkerofs/main.go
deleted file mode 100644
index b5d5568..0000000
--- a/metropolis/node/build/mkerofs/main.go
+++ /dev/null
@@ -1,208 +0,0 @@
-// Copyright 2020 The Monogon Project Authors.
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// mkerofs takes a specification in the form of a prototext file (see fsspec
-// next to this) and assembles an EROFS filesystem according to it. The output
-// is fully reproducible.
-package main
-
-import (
- "flag"
- "fmt"
- "io"
- "log"
- "os"
- "path"
- "sort"
- "strings"
-
- "source.monogon.dev/metropolis/node/build/fsspec"
- "source.monogon.dev/osbase/erofs"
-)
-
-func (spec *entrySpec) writeRecursive(w *erofs.Writer, pathname string) {
- switch inode := spec.data.Type.(type) {
- case *fsspec.Inode_Directory:
- // Sort children for reproducibility
- var sortedChildren []string
- for name := range spec.children {
- sortedChildren = append(sortedChildren, name)
- }
- sort.Strings(sortedChildren)
-
- err := w.Create(pathname, &erofs.Directory{
- Base: erofs.Base{
- Permissions: uint16(inode.Directory.Mode),
- UID: uint16(inode.Directory.Uid),
- GID: uint16(inode.Directory.Gid),
- },
- Children: sortedChildren,
- })
- if err != nil {
- log.Fatalf("failed to write directory: %s", err)
- }
- for _, name := range sortedChildren {
- spec.children[name].writeRecursive(w, path.Join(pathname, name))
- }
- case *fsspec.Inode_File:
- iw := w.CreateFile(pathname, &erofs.FileMeta{
- Base: erofs.Base{
- Permissions: uint16(inode.File.Mode),
- UID: uint16(inode.File.Uid),
- GID: uint16(inode.File.Gid),
- },
- })
-
- sourceFile, err := os.Open(inode.File.SourcePath)
- if err != nil {
- log.Fatalf("failed to open source file %s: %s", inode.File.SourcePath, err)
- }
-
- _, err = io.Copy(iw, sourceFile)
- if err != nil {
- log.Fatalf("failed to copy file into filesystem: %s", err)
- }
- sourceFile.Close()
- if err := iw.Close(); err != nil {
- log.Fatalf("failed to close target file: %s", err)
- }
- case *fsspec.Inode_SymbolicLink:
- err := w.Create(pathname, &erofs.SymbolicLink{
- Base: erofs.Base{
- Permissions: 0777, // Nominal, Linux forces that mode anyways, see symlink(7)
- },
- Target: inode.SymbolicLink.TargetPath,
- })
- if err != nil {
- log.Fatalf("failed to create symbolic link: %s", err)
- }
- case *fsspec.Inode_SpecialFile:
- err := fmt.Errorf("unimplemented special file type %s", inode.SpecialFile.Type)
- base := erofs.Base{
- Permissions: uint16(inode.SpecialFile.Mode),
- UID: uint16(inode.SpecialFile.Uid),
- GID: uint16(inode.SpecialFile.Gid),
- }
- switch inode.SpecialFile.Type {
- case fsspec.SpecialFile_FIFO:
- err = w.Create(pathname, &erofs.FIFO{
- Base: base,
- })
- case fsspec.SpecialFile_CHARACTER_DEV:
- err = w.Create(pathname, &erofs.CharacterDevice{
- Base: base,
- Major: inode.SpecialFile.Major,
- Minor: inode.SpecialFile.Minor,
- })
- case fsspec.SpecialFile_BLOCK_DEV:
- err = w.Create(pathname, &erofs.BlockDevice{
- Base: base,
- Major: inode.SpecialFile.Major,
- Minor: inode.SpecialFile.Minor,
- })
- }
- if err != nil {
- log.Fatalf("failed to make special file: %v", err)
- }
- }
-}
-
-// entrySpec is a recursive structure representing the filesystem tree
-type entrySpec struct {
- data fsspec.Inode
- children map[string]*entrySpec
-}
-
-// pathRef gets the entrySpec at the leaf of the given path, inferring
-// directories if necessary
-func (spec *entrySpec) pathRef(p string) *entrySpec {
- // This block gets a path array starting at the root of the filesystem. The
- // root folder is the zero-length array.
- pathParts := strings.Split(path.Clean("./"+p), "/")
- if pathParts[0] == "." {
- pathParts = pathParts[1:]
- }
-
- entryRef := spec
- for _, part := range pathParts {
- childRef, ok := entryRef.children[part]
- if !ok {
- childRef = &entrySpec{
- data: fsspec.Inode{Type: &fsspec.Inode_Directory{Directory: &fsspec.Directory{Mode: 0555}}},
- children: make(map[string]*entrySpec),
- }
- entryRef.children[part] = childRef
- }
- entryRef = childRef
- }
- return entryRef
-}
-
-var (
- outPath = flag.String("out", "", "Output file path")
-)
-
-func main() {
- flag.Parse()
-
- spec, err := fsspec.ReadMergeSpecs(flag.Args())
- if err != nil {
- log.Fatalf("failed to load specs: %v", err)
- }
-
- var fsRoot = &entrySpec{
- data: fsspec.Inode{Type: &fsspec.Inode_Directory{Directory: &fsspec.Directory{Mode: 0555}}},
- children: make(map[string]*entrySpec),
- }
-
- for _, dir := range spec.Directory {
- entryRef := fsRoot.pathRef(dir.Path)
- entryRef.data.Type = &fsspec.Inode_Directory{Directory: dir}
- }
-
- for _, file := range spec.File {
- entryRef := fsRoot.pathRef(file.Path)
- entryRef.data.Type = &fsspec.Inode_File{File: file}
- }
-
- for _, symlink := range spec.SymbolicLink {
- entryRef := fsRoot.pathRef(symlink.Path)
- entryRef.data.Type = &fsspec.Inode_SymbolicLink{SymbolicLink: symlink}
- }
-
- for _, specialFile := range spec.SpecialFile {
- entryRef := fsRoot.pathRef(specialFile.Path)
- entryRef.data.Type = &fsspec.Inode_SpecialFile{SpecialFile: specialFile}
- }
-
- fs, err := os.Create(*outPath)
- if err != nil {
- log.Fatalf("failed to open output file: %v", err)
- }
- writer, err := erofs.NewWriter(fs)
- if err != nil {
- log.Fatalf("failed to initialize EROFS writer: %v", err)
- }
-
- fsRoot.writeRecursive(writer, ".")
-
- if err := writer.Close(); err != nil {
- panic(err)
- }
- if err := fs.Close(); err != nil {
- panic(err)
- }
-}
diff --git a/metropolis/node/build/mkimage/BUILD.bazel b/metropolis/node/build/mkimage/BUILD.bazel
deleted file mode 100644
index 41ce603..0000000
--- a/metropolis/node/build/mkimage/BUILD.bazel
+++ /dev/null
@@ -1,22 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
-
-go_library(
- name = "mkimage_lib",
- srcs = ["main.go"],
- embedsrcs = [
- "//metropolis/node/core/abloader", #keep
- ],
- importpath = "source.monogon.dev/metropolis/node/build/mkimage",
- visibility = ["//visibility:private"],
- deps = [
- "//metropolis/node/build/mkimage/osimage",
- "//osbase/blkio",
- "//osbase/blockdev",
- ],
-)
-
-go_binary(
- name = "mkimage",
- embed = [":mkimage_lib"],
- visibility = ["//metropolis/node:__pkg__"],
-)
diff --git a/metropolis/node/build/mkimage/def.bzl b/metropolis/node/build/mkimage/def.bzl
deleted file mode 100644
index efcebdc..0000000
--- a/metropolis/node/build/mkimage/def.bzl
+++ /dev/null
@@ -1,48 +0,0 @@
-def _node_image_impl(ctx):
- img_file = ctx.actions.declare_file(ctx.label.name + ".img")
- ctx.actions.run(
- mnemonic = "MkImage",
- executable = ctx.executable._mkimage,
- arguments = [
- "-efi",
- ctx.file.kernel.path,
- "-system",
- ctx.file.system.path,
- "-out",
- img_file.path,
- ],
- inputs = [
- ctx.file.kernel,
- ctx.file.system,
- ],
- outputs = [img_file],
- )
-
- return [DefaultInfo(files = depset([img_file]), runfiles = ctx.runfiles(files = [img_file]))]
-
-node_image = rule(
- implementation = _node_image_impl,
- doc = """
- Build a disk image from an EFI kernel payload and system partition
- contents. See //metropolis/node/build/mkimage for more information.
- """,
- attrs = {
- "kernel": attr.label(
- doc = "EFI binary containing a kernel.",
- mandatory = True,
- allow_single_file = True,
- ),
- "system": attr.label(
- doc = "Contents of the system partition.",
- mandatory = True,
- allow_single_file = True,
- ),
- "_mkimage": attr.label(
- doc = "The mkimage executable.",
- default = "//metropolis/node/build/mkimage",
- allow_single_file = True,
- executable = True,
- cfg = "exec",
- ),
- },
-)
diff --git a/metropolis/node/build/mkimage/main.go b/metropolis/node/build/mkimage/main.go
deleted file mode 100644
index 3a68fc7..0000000
--- a/metropolis/node/build/mkimage/main.go
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2020 The Monogon Project Authors.
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// mkimage is a tool to generate Metropolis node disk images.
-// It can be used both to initialize block devices and to create image
-// files.
-//
-// The tool takes a path to an EFI payload (--efi), and a path to a
-// Metropolis system image (--system) as its only required inputs. In
-// addition, an output path must be supplied (--out).
-// Node parameters file path (--node_parameters) may also be supplied, in
-// which case the file will be copied to the EFI system partition.
-// Partition sizes are fixed and may be overridden by command line flags.
-package main
-
-import (
- "bytes"
- _ "embed"
- "flag"
- "log"
- "os"
-
- "source.monogon.dev/metropolis/node/build/mkimage/osimage"
- "source.monogon.dev/osbase/blkio"
- "source.monogon.dev/osbase/blockdev"
-)
-
-//go:embed metropolis/node/core/abloader/abloader_bin.efi
-var abloader []byte
-
-func main() {
- // Fill in the image parameters based on flags.
- var (
- efiPayload string
- systemImage string
- nodeParams string
- outputPath string
- diskUUID string
- cfg osimage.Params
- )
- flag.StringVar(&efiPayload, "efi", "", "Path to the UEFI payload used")
- flag.StringVar(&systemImage, "system", "", "Path to the system partition image used")
- flag.StringVar(&nodeParams, "node_parameters", "", "Path to Node Parameters to be written to the ESP (default: don't write Node Parameters)")
- flag.StringVar(&outputPath, "out", "", "Path to the resulting disk image or block device")
- flag.Int64Var(&cfg.PartitionSize.Data, "data_partition_size", 2048, "Override the data partition size (default 2048 MiB). Used only when generating image files.")
- flag.Int64Var(&cfg.PartitionSize.ESP, "esp_partition_size", 128, "Override the ESP partition size (default: 128MiB)")
- flag.Int64Var(&cfg.PartitionSize.System, "system_partition_size", 1024, "Override the System partition size (default: 1024MiB)")
- flag.StringVar(&diskUUID, "GUID", "", "Disk GUID marked in the resulting image's partition table (default: randomly generated)")
- flag.Parse()
-
- // Open the input files for osimage.Create, fill in reader objects and
- // metadata in osimage.Params.
- // Start with the EFI Payload the OS will boot from.
- p, err := blkio.NewFileReader(efiPayload)
- if err != nil {
- log.Fatalf("while opening the EFI payload at %q: %v", efiPayload, err)
- }
- cfg.EFIPayload = p
-
- // Attempt to open the system image if its path is set. In case the path
- // isn't set, the system partition will still be created, but no
- // contents will be written into it.
- if systemImage != "" {
- img, err := os.Open(systemImage)
- if err != nil {
- log.Fatalf("while opening the system image at %q: %v", systemImage, err)
- }
- defer img.Close()
- cfg.SystemImage = img
- }
-
- // Attempt to open the node parameters file if its path is set.
- if nodeParams != "" {
- np, err := blkio.NewFileReader(nodeParams)
- if err != nil {
- log.Fatalf("while opening node parameters at %q: %v", nodeParams, err)
- }
- cfg.NodeParameters = np
- }
-
- // TODO(#254): Build and use dynamically-grown block devices
- cfg.Output, err = blockdev.CreateFile(outputPath, 512, 10*1024*1024)
- if err != nil {
- panic(err)
- }
-
- cfg.ABLoader = bytes.NewReader(abloader)
-
- // Write the parametrized OS image.
- if _, err := osimage.Write(&cfg); err != nil {
- log.Fatalf("while creating a Metropolis OS image: %v", err)
- }
-}
diff --git a/metropolis/node/build/mkimage/osimage/BUILD.bazel b/metropolis/node/build/mkimage/osimage/BUILD.bazel
deleted file mode 100644
index 9799b81..0000000
--- a/metropolis/node/build/mkimage/osimage/BUILD.bazel
+++ /dev/null
@@ -1,15 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_library")
-
-go_library(
- name = "osimage",
- srcs = ["osimage.go"],
- importpath = "source.monogon.dev/metropolis/node/build/mkimage/osimage",
- visibility = ["//visibility:public"],
- deps = [
- "//osbase/blockdev",
- "//osbase/efivarfs",
- "//osbase/fat32",
- "//osbase/gpt",
- "@com_github_google_uuid//:uuid",
- ],
-)
diff --git a/metropolis/node/build/mkimage/osimage/osimage.go b/metropolis/node/build/mkimage/osimage/osimage.go
deleted file mode 100644
index d139d6b..0000000
--- a/metropolis/node/build/mkimage/osimage/osimage.go
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright 2020 The Monogon Project Authors.
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// This package provides self-contained implementation used to generate
-// Metropolis disk images.
-package osimage
-
-import (
- "fmt"
- "io"
- "strings"
-
- "github.com/google/uuid"
-
- "source.monogon.dev/osbase/blockdev"
- "source.monogon.dev/osbase/efivarfs"
- "source.monogon.dev/osbase/fat32"
- "source.monogon.dev/osbase/gpt"
-)
-
-var (
- SystemAType = uuid.MustParse("ee96054b-f6d0-4267-aaaa-724b2afea74c")
- SystemBType = uuid.MustParse("ee96054b-f6d0-4267-bbbb-724b2afea74c")
-
- DataType = uuid.MustParse("9eeec464-6885-414a-b278-4305c51f7966")
-)
-
-const (
- SystemALabel = "METROPOLIS-SYSTEM-A"
- SystemBLabel = "METROPOLIS-SYSTEM-B"
- DataLabel = "METROPOLIS-NODE-DATA"
- ESPLabel = "ESP"
-
- EFIPayloadPath = "/EFI/BOOT/BOOTx64.EFI"
- EFIBootAPath = "/EFI/metropolis/boot-a.efi"
- EFIBootBPath = "/EFI/metropolis/boot-b.efi"
- nodeParamsPath = "metropolis/parameters.pb"
-)
-
-// PartitionSizeInfo contains parameters used during partition table
-// initialization and, in case of image files, space allocation.
-type PartitionSizeInfo struct {
- // Size of the EFI System Partition (ESP), in mebibytes. The size must
- // not be zero.
- ESP int64
- // Size of the Metropolis system partition, in mebibytes. The partition
- // won't be created if the size is zero.
- System int64
- // Size of the Metropolis data partition, in mebibytes. The partition
- // won't be created if the size is zero. If the image is output to a
- // block device, the partition will be extended to fill the remaining
- // space.
- Data int64
-}
-
-// Params contains parameters used by Plan or Write to build a Metropolis OS
-// image.
-type Params struct {
- // Output is the block device to which the OS image is written.
- Output blockdev.BlockDev
- // ABLoader provides the A/B loader which then loads the EFI loader for the
- // correct slot.
- ABLoader fat32.SizedReader
- // EFIPayload provides contents of the EFI payload file. It must not be
- // nil. This gets put into boot slot A.
- EFIPayload fat32.SizedReader
- // SystemImage provides contents of the Metropolis system partition.
- // If nil, no contents will be copied into the partition.
- SystemImage io.Reader
- // NodeParameters provides contents of the node parameters file. If nil,
- // the node parameters file won't be created in the target ESP
- // filesystem.
- NodeParameters fat32.SizedReader
- // DiskGUID is a unique identifier of the image and a part of Table
- // header. It's optional and can be left blank if the identifier is
- // to be randomly generated. Setting it to a predetermined value can
- // help in implementing reproducible builds.
- DiskGUID uuid.UUID
- // PartitionSize specifies a size for the ESP, Metropolis System and
- // Metropolis data partition.
- PartitionSize PartitionSizeInfo
-}
-
-type plan struct {
- *Params
- rootInode fat32.Inode
- tbl *gpt.Table
- efiPartition *gpt.Partition
- systemPartitionA *gpt.Partition
- systemPartitionB *gpt.Partition
- dataPartition *gpt.Partition
-}
-
-// Apply actually writes the planned installation to the blockdevice.
-func (i *plan) Apply() (*efivarfs.LoadOption, error) {
- // Discard the entire device, we're going to write new data over it.
- // Ignore errors, this is only advisory.
- i.Output.Discard(0, i.Output.BlockCount()*i.Output.BlockSize())
-
- if err := fat32.WriteFS(blockdev.NewRWS(i.efiPartition), i.rootInode, fat32.Options{
- BlockSize: uint16(i.efiPartition.BlockSize()),
- BlockCount: uint32(i.efiPartition.BlockCount()),
- Label: "MNGN_BOOT",
- }); err != nil {
- return nil, fmt.Errorf("failed to write FAT32: %w", err)
- }
-
- if _, err := io.Copy(blockdev.NewRWS(i.systemPartitionA), i.SystemImage); err != nil {
- return nil, fmt.Errorf("failed to write system partition A: %w", err)
- }
-
- if err := i.tbl.Write(); err != nil {
- return nil, fmt.Errorf("failed to write Table: %w", err)
- }
-
- // Build an EFI boot entry pointing to the image's ESP.
- return &efivarfs.LoadOption{
- Description: "Metropolis",
- FilePath: efivarfs.DevicePath{
- &efivarfs.HardDrivePath{
- PartitionNumber: 1,
- PartitionStartBlock: i.efiPartition.FirstBlock,
- PartitionSizeBlocks: i.efiPartition.SizeBlocks(),
- PartitionMatch: efivarfs.PartitionGPT{
- PartitionUUID: i.efiPartition.ID,
- },
- },
- efivarfs.FilePath(EFIPayloadPath),
- },
- }, nil
-}
-
-// Plan allows to prepare an installation without modifying any data on the
-// system. To apply the planned installation, call Apply on the returned plan.
-func Plan(p *Params) (*plan, error) {
- params := &plan{Params: p}
-
- var err error
- params.tbl, err = gpt.New(params.Output)
- if err != nil {
- return nil, fmt.Errorf("invalid block device: %w", err)
- }
-
- params.tbl.ID = params.DiskGUID
- params.efiPartition = &gpt.Partition{
- Type: gpt.PartitionTypeEFISystem,
- Name: ESPLabel,
- }
-
- if err := params.tbl.AddPartition(params.efiPartition, params.PartitionSize.ESP*Mi); err != nil {
- return nil, fmt.Errorf("failed to allocate ESP: %w", err)
- }
-
- params.rootInode = fat32.Inode{
- Attrs: fat32.AttrDirectory,
- }
- if err := params.rootInode.PlaceFile(strings.TrimPrefix(EFIBootAPath, "/"), params.EFIPayload); err != nil {
- return nil, err
- }
- // Place the A/B loader at the EFI bootloader autodiscovery path.
- if err := params.rootInode.PlaceFile(strings.TrimPrefix(EFIPayloadPath, "/"), params.ABLoader); err != nil {
- return nil, err
- }
- if params.NodeParameters != nil {
- if err := params.rootInode.PlaceFile(nodeParamsPath, params.NodeParameters); err != nil {
- return nil, err
- }
- }
-
- // Try to layout the fat32 partition. If it detects that the disk is too
- // small, an error will be returned.
- if _, err := fat32.SizeFS(params.rootInode, fat32.Options{
- BlockSize: uint16(params.efiPartition.BlockSize()),
- BlockCount: uint32(params.efiPartition.BlockCount()),
- Label: "MNGN_BOOT",
- }); err != nil {
- return nil, fmt.Errorf("failed to calculate size of FAT32: %w", err)
- }
-
- // Create the system partition only if its size is specified.
- if params.PartitionSize.System != 0 && params.SystemImage != nil {
- params.systemPartitionA = &gpt.Partition{
- Type: SystemAType,
- Name: SystemALabel,
- }
- if err := params.tbl.AddPartition(params.systemPartitionA, params.PartitionSize.System*Mi); err != nil {
- return nil, fmt.Errorf("failed to allocate system partition A: %w", err)
- }
- params.systemPartitionB = &gpt.Partition{
- Type: SystemBType,
- Name: SystemBLabel,
- }
- if err := params.tbl.AddPartition(params.systemPartitionB, params.PartitionSize.System*Mi); err != nil {
- return nil, fmt.Errorf("failed to allocate system partition B: %w", err)
- }
- } else if params.PartitionSize.System == 0 && params.SystemImage != nil {
- // Safeguard against contradicting parameters.
- return nil, fmt.Errorf("the system image parameter was passed while the associated partition size is zero")
- }
- // Create the data partition only if its size is specified.
- if params.PartitionSize.Data != 0 {
- params.dataPartition = &gpt.Partition{
- Type: DataType,
- Name: DataLabel,
- }
- if err := params.tbl.AddPartition(params.dataPartition, -1); err != nil {
- return nil, fmt.Errorf("failed to allocate data partition: %w", err)
- }
- }
-
- return params, nil
-}
-
-const Mi = 1024 * 1024
-
-// Write writes a Metropolis OS image to a block device.
-func Write(params *Params) (*efivarfs.LoadOption, error) {
- p, err := Plan(params)
- if err != nil {
- return nil, err
- }
-
- return p.Apply()
-}
diff --git a/metropolis/node/build/mkpayload/BUILD.bazel b/metropolis/node/build/mkpayload/BUILD.bazel
deleted file mode 100644
index b092791..0000000
--- a/metropolis/node/build/mkpayload/BUILD.bazel
+++ /dev/null
@@ -1,14 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
-
-go_binary(
- name = "mkpayload",
- embed = [":mkpayload_lib"],
- visibility = ["//visibility:public"],
-)
-
-go_library(
- name = "mkpayload_lib",
- srcs = ["mkpayload.go"],
- importpath = "source.monogon.dev/metropolis/node/build/mkpayload",
- visibility = ["//visibility:private"],
-)
diff --git a/metropolis/node/build/mkpayload/mkpayload.go b/metropolis/node/build/mkpayload/mkpayload.go
deleted file mode 100644
index a66d458..0000000
--- a/metropolis/node/build/mkpayload/mkpayload.go
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2020 The Monogon Project Authors.
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// mkpayload is an objcopy wrapper that builds EFI unified kernel images. It
-// performs actions that can't be realized by either objcopy or the
-// buildsystem.
-package main
-
-import (
- "errors"
- "flag"
- "fmt"
- "io"
- "log"
- "os"
- "os/exec"
- "strings"
-)
-
-type stringList []string
-
-func (l *stringList) String() string {
- if l == nil {
- return ""
- }
- return strings.Join(*l, ", ")
-}
-
-func (l *stringList) Set(value string) error {
- *l = append(*l, value)
- return nil
-}
-
-var (
- // sections contains VMAs and source files of the payload PE sections. The
- // file path pointers will be filled in when the flags are parsed. It's used
- // to generate objcopy command line arguments. Entries that are "required"
- // will cause the program to stop and print usage information if not provided
- // as command line parameters.
- sections = map[string]struct {
- descr string
- vma string
- required bool
- file *string
- }{
- "linux": {"Linux kernel image", "0x2000000", true, nil},
- "initrd": {"initramfs", "0x5000000", false, nil},
- "osrel": {"OS release file in text format", "0x20000", false, nil},
- "cmdline": {"a file containting additional kernel command line parameters", "0x30000", false, nil},
- "splash": {"a splash screen image in BMP format", "0x40000", false, nil},
- }
- initrdList stringList
- objcopy = flag.String("objcopy", "", "objcopy executable")
- stub = flag.String("stub", "", "the EFI stub executable")
- output = flag.String("output", "", "objcopy output")
- rootfs_dm_table = flag.String("rootfs_dm_table", "", "a text file containing the DeviceMapper rootfs target table")
-)
-
-func main() {
- flag.Var(&initrdList, "initrd", "Path to initramfs, can be given multiple times")
- // Register parameters related to the EFI payload sections, then parse the flags.
- for k, v := range sections {
- if k == "initrd" { // initrd is special because it accepts multiple payloads
- continue
- }
- v.file = flag.String(k, "", v.descr)
- sections[k] = v
- }
- flag.Parse()
-
- // Ensure all the required parameters are filled in.
- for n, s := range sections {
- if s.required && *s.file == "" {
- log.Fatalf("-%s parameter is missing.", n)
- }
- }
- if *objcopy == "" {
- log.Fatalf("-objcopy parameter is missing.")
- }
- if *stub == "" {
- log.Fatalf("-stub parameter is missing.")
- }
- if *output == "" {
- log.Fatalf("-output parameter is missing.")
- }
-
- // If a DeviceMapper table was passed, configure the kernel to boot from the
- // device described by it, while keeping any other kernel command line
- // parameters that might have been passed through "-cmdline".
- if *rootfs_dm_table != "" {
- var cmdline string
- p := *sections["cmdline"].file
- if p != "" {
- c, err := os.ReadFile(p)
- if err != nil {
- log.Fatalf("%v", err)
- }
- cmdline = string(c[:])
-
- if strings.Contains(cmdline, "root=") {
- log.Fatalf("A DeviceMapper table was passed, however the kernel command line already contains a \"root=\" statement.")
- }
- }
-
- vt, err := os.ReadFile(*rootfs_dm_table)
- if err != nil {
- log.Fatalf("%v", err)
- }
- cmdline += fmt.Sprintf(" dm-mod.create=\"rootfs,,,ro,%s\" root=/dev/dm-0", vt)
-
- out, err := os.CreateTemp(".", "cmdline")
- if err != nil {
- log.Fatalf("%v", err)
- }
- defer os.Remove(out.Name())
- if _, err = out.Write([]byte(cmdline[:])); err != nil {
- log.Fatalf("%v", err)
- }
- out.Close()
-
- *sections["cmdline"].file = out.Name()
- }
-
- var initrdPath string
- if len(initrdList) > 0 {
- initrd, err := os.CreateTemp(".", "initrd")
- if err != nil {
- log.Fatalf("Failed to create temporary initrd: %v", err)
- }
- defer os.Remove(initrd.Name())
- for _, initrdPath := range initrdList {
- initrdSrc, err := os.Open(initrdPath)
- if err != nil {
- log.Fatalf("Failed to open initrd file: %v", err)
- }
- if _, err := io.Copy(initrd, initrdSrc); err != nil {
- initrdSrc.Close()
- log.Fatalf("Failed concatinating initrd: %v", err)
- }
- initrdSrc.Close()
- }
- initrdPath = initrd.Name()
- }
- sec := sections["initrd"]
- sec.file = &initrdPath
- sections["initrd"] = sec
-
- // Execute objcopy
- var args []string
- for name, c := range sections {
- if *c.file != "" {
- args = append(args, []string{
- "--add-section", fmt.Sprintf(".%s=%s", name, *c.file),
- "--change-section-vma", fmt.Sprintf(".%s=%s", name, c.vma),
- }...)
- }
- }
- args = append(args, []string{
- *stub,
- *output,
- }...)
- cmd := exec.Command(*objcopy, args...)
- cmd.Stderr = os.Stderr
- cmd.Stdout = os.Stdout
- err := cmd.Run()
- if err == nil {
- return
- }
- // Exit with objcopy's return code.
- var e *exec.ExitError
- if errors.As(err, &e) {
- os.Exit(e.ExitCode())
- }
- log.Fatalf("Could not start command: %v", err)
-}
diff --git a/metropolis/node/build/mkucode/BUILD.bazel b/metropolis/node/build/mkucode/BUILD.bazel
deleted file mode 100644
index c1f5667..0000000
--- a/metropolis/node/build/mkucode/BUILD.bazel
+++ /dev/null
@@ -1,19 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
-
-go_library(
- name = "mkucode_lib",
- srcs = ["main.go"],
- importpath = "source.monogon.dev/metropolis/node/build/mkucode",
- visibility = ["//visibility:private"],
- deps = [
- "//metropolis/node/build/mkucode/spec",
- "@com_github_cavaliergopher_cpio//:cpio",
- "@org_golang_google_protobuf//encoding/prototext",
- ],
-)
-
-go_binary(
- name = "mkucode",
- embed = [":mkucode_lib"],
- visibility = ["//visibility:public"],
-)
diff --git a/metropolis/node/build/mkucode/def.bzl b/metropolis/node/build/mkucode/def.bzl
deleted file mode 100644
index 3faa775..0000000
--- a/metropolis/node/build/mkucode/def.bzl
+++ /dev/null
@@ -1,45 +0,0 @@
-def _cpio_ucode_impl(ctx):
- ucode_spec = ctx.actions.declare_file(ctx.label.name + "_spec.prototxt")
-
- vendors = []
- inputs = []
- for label, vendor in ctx.attr.ucode.items():
- files = label[DefaultInfo].files.to_list()
- inputs += files
- vendors.append(struct(id = vendor, file = [f.path for f in files]))
-
- ctx.actions.write(ucode_spec, proto.encode_text(struct(vendor = vendors)))
-
- output_file = ctx.actions.declare_file(ctx.label.name + ".cpio")
- ctx.actions.run(
- outputs = [output_file],
- inputs = [ucode_spec] + inputs,
- tools = [ctx.executable._mkucode],
- executable = ctx.executable._mkucode,
- arguments = ["-out", output_file.path, "-spec", ucode_spec.path],
- )
- return [DefaultInfo(files = depset([output_file]))]
-
-cpio_ucode = rule(
- implementation = _cpio_ucode_impl,
- doc = """
- Builds a cpio archive with microcode for the Linux early microcode loader.
- """,
- attrs = {
- "ucode": attr.label_keyed_string_dict(
- mandatory = True,
- allow_files = True,
- doc = """
- Dictionary of Labels to String. Each label is a list of microcode files and the string label
- is the vendor ID corresponding to that microcode.
- """,
- ),
-
- # Tool
- "_mkucode": attr.label(
- default = Label("//metropolis/node/build/mkucode"),
- executable = True,
- cfg = "exec",
- ),
- },
-)
diff --git a/metropolis/node/build/mkucode/main.go b/metropolis/node/build/mkucode/main.go
deleted file mode 100644
index 1cd8960..0000000
--- a/metropolis/node/build/mkucode/main.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// This assembles standalone microcode files into the format expected by the
-// Linux microcode loader. See
-// https://www.kernel.org/doc/html/latest/x86/microcode.html for further
-// information.
-package main
-
-import (
- "flag"
- "io"
- "log"
- "os"
-
- "github.com/cavaliergopher/cpio"
- "google.golang.org/protobuf/encoding/prototext"
-
- "source.monogon.dev/metropolis/node/build/mkucode/spec"
-)
-
-var (
- specPath = flag.String("spec", "", "Path to prototext specification (metropolis.node.build.mkucode.UCode)")
- outPath = flag.String("out", "", "Output path for cpio to be prepend to initrd")
-)
-
-// Usage: -spec <ucode.prototxt> -out <ucode.cpio>
-func main() {
- flag.Parse()
- specRaw, err := os.ReadFile(*specPath)
- if err != nil {
- log.Fatalf("Failed to read spec: %v", err)
- }
- var ucodeSpec spec.UCode
- if err := prototext.Unmarshal(specRaw, &ucodeSpec); err != nil {
- log.Fatalf("Failed unmarshaling ucode spec: %v", err)
- }
- out, err := os.Create(*outPath)
- if err != nil {
- log.Fatalf("Failed to create cpio: %v", err)
- }
- defer out.Close()
- cpioWriter := cpio.NewWriter(out)
- for _, vendor := range ucodeSpec.Vendor {
- var totalSize int64
- for _, file := range vendor.File {
- data, err := os.Stat(file)
- if err != nil {
- log.Fatalf("Failed to stat file for vendor %q: %v", vendor.Id, err)
- }
- totalSize += data.Size()
- }
- if err := cpioWriter.WriteHeader(&cpio.Header{
- Mode: 0444,
- Name: "kernel/x86/microcode/" + vendor.Id + ".bin",
- Size: totalSize,
- }); err != nil {
- log.Fatalf("Failed to write cpio header for vendor %q: %v", vendor.Id, err)
- }
- for _, file := range vendor.File {
- f, err := os.Open(file)
- if err != nil {
- log.Fatalf("Failed to open file for vendor %q: %v", vendor.Id, err)
- }
- if _, err := io.Copy(cpioWriter, f); err != nil {
- log.Fatalf("Failed to copy data for file %q: %v", file, err)
- }
- f.Close()
- }
- }
- if err := cpioWriter.Close(); err != nil {
- log.Fatalf("Failed writing cpio: %v", err)
- }
-}
diff --git a/metropolis/node/build/mkucode/spec/BUILD.bazel b/metropolis/node/build/mkucode/spec/BUILD.bazel
deleted file mode 100644
index 84e7c7b..0000000
--- a/metropolis/node/build/mkucode/spec/BUILD.bazel
+++ /dev/null
@@ -1,30 +0,0 @@
-load("@rules_proto//proto:defs.bzl", "proto_library")
-load("@io_bazel_rules_go//go:def.bzl", "go_library")
-load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
-
-proto_library(
- name = "mkucode_proto",
- srcs = ["spec.proto"],
- visibility = ["//visibility:public"],
-)
-
-go_proto_library(
- name = "mkucode_go_proto",
- importpath = "source.monogon.dev/metropolis/node/build/mkucode",
- proto = ":mkucode_proto",
- visibility = ["//visibility:public"],
-)
-
-go_library(
- name = "spec",
- embed = [":spec_go_proto"],
- importpath = "source.monogon.dev/metropolis/node/build/mkucode/spec",
- visibility = ["//visibility:public"],
-)
-
-go_proto_library(
- name = "spec_go_proto",
- importpath = "source.monogon.dev/metropolis/node/build/mkucode/spec",
- proto = ":mkucode_proto",
- visibility = ["//visibility:public"],
-)
diff --git a/metropolis/node/build/mkucode/spec/gomod-generated-placeholder.go b/metropolis/node/build/mkucode/spec/gomod-generated-placeholder.go
deleted file mode 100644
index f09cd57..0000000
--- a/metropolis/node/build/mkucode/spec/gomod-generated-placeholder.go
+++ /dev/null
@@ -1 +0,0 @@
-package spec
diff --git a/metropolis/node/build/mkucode/spec/spec.proto b/metropolis/node/build/mkucode/spec/spec.proto
deleted file mode 100644
index ed537c5..0000000
--- a/metropolis/node/build/mkucode/spec/spec.proto
+++ /dev/null
@@ -1,17 +0,0 @@
-syntax = "proto3";
-
-package metropolis.node.build.mkucode;
-option go_package = "source.monogon.dev/metropolis/node/build/mkucode/spec";
-
-message UCode {
- repeated UCodeVendor vendor = 1;
-}
-
-message UCodeVendor {
- // The vendor id (as given in cpuid) of the CPU the microcode is for, like
- // GenuineIntel or AuthenticAMD.
- string id = 1;
-
- // List of paths to microcode files from for CPUs from the vendor.
- repeated string file = 2;
-}
\ No newline at end of file
diff --git a/metropolis/node/build/mkverity/BUILD.bazel b/metropolis/node/build/mkverity/BUILD.bazel
deleted file mode 100644
index a748b86..0000000
--- a/metropolis/node/build/mkverity/BUILD.bazel
+++ /dev/null
@@ -1,19 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
-
-go_binary(
- name = "mkverity",
- embed = [":mkverity_lib"],
- visibility = [
- "//metropolis/installer/test/testos:__pkg__",
- "//metropolis/node:__pkg__",
- "//metropolis/node/core/update/e2e/testos:__pkg__",
- ],
-)
-
-go_library(
- name = "mkverity_lib",
- srcs = ["mkverity.go"],
- importpath = "source.monogon.dev/metropolis/node/build/mkverity",
- visibility = ["//visibility:private"],
- deps = ["//osbase/verity"],
-)
diff --git a/metropolis/node/build/mkverity/mkverity.go b/metropolis/node/build/mkverity/mkverity.go
deleted file mode 100644
index ff2807b..0000000
--- a/metropolis/node/build/mkverity/mkverity.go
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright 2020 The Monogon Project Authors.
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// This package implements a command line tool that creates dm-verity hash
-// images at a selected path, given an existing data image. The tool
-// outputs a Verity mapping table on success.
-//
-// For more information, see:
-// - source.monogon.dev/osbase/verity
-// - https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity
-package main
-
-import (
- "flag"
- "fmt"
- "io"
- "log"
- "os"
-
- "source.monogon.dev/osbase/verity"
-)
-
-// createImage creates a dm-verity target image by combining the input image
-// with Verity metadata. Contents of the data image are copied to the output
-// image. Then, the same contents are verity-encoded and appended to the
-// output image. The verity superblock is written only if wsb is true. It
-// returns either a dm-verity target table, or an error.
-func createImage(dataImagePath, outputImagePath string, wsb bool) (*verity.MappingTable, error) {
- // Hardcode both the data block size and the hash block size as 4096 bytes.
- bs := uint32(4096)
-
- // Open the data image for reading.
- dataImage, err := os.Open(dataImagePath)
- if err != nil {
- return nil, fmt.Errorf("while opening the data image: %w", err)
- }
- defer dataImage.Close()
-
- // Check that the data image is well-formed.
- ds, err := dataImage.Stat()
- if err != nil {
- return nil, fmt.Errorf("while stat-ing the data image: %w", err)
- }
- if !ds.Mode().IsRegular() {
- return nil, fmt.Errorf("the data image must be a regular file")
- }
- if ds.Size()%int64(bs) != 0 {
- return nil, fmt.Errorf("the data image must end on a %d-byte block boundary", bs)
- }
-
- // Create an empty hash image file.
- outputImage, err := os.OpenFile(outputImagePath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0644)
- if err != nil {
- return nil, fmt.Errorf("while opening the hash image for writing: %w", err)
- }
- defer outputImage.Close()
-
- // Copy the input data into the output file, then rewind dataImage to be read
- // again by the Verity encoder.
- _, err = io.Copy(outputImage, dataImage)
- if err != nil {
- return nil, err
- }
- _, err = dataImage.Seek(0, os.SEEK_SET)
- if err != nil {
- return nil, err
- }
-
- // Write outputImage contents. Start with initializing a verity encoder,
- // seting outputImage as its output.
- v, err := verity.NewEncoder(outputImage, bs, bs, wsb)
- if err != nil {
- return nil, fmt.Errorf("while initializing a verity encoder: %w", err)
- }
- // Hash the contents of dataImage, block by block.
- _, err = io.Copy(v, dataImage)
- if err != nil {
- return nil, fmt.Errorf("while reading the data image: %w", err)
- }
- // The resulting hash tree won't be written until Close is called.
- err = v.Close()
- if err != nil {
- return nil, fmt.Errorf("while writing the hash image: %w", err)
- }
-
- // Return an encoder-generated verity mapping table, containing the salt and
- // the root hash. First, calculate the starting hash block by dividing the
- // data image size by the encoder data block size.
- hashStart := ds.Size() / int64(bs)
- mt, err := v.MappingTable(dataImagePath, outputImagePath, hashStart)
- if err != nil {
- return nil, fmt.Errorf("while querying for the mapping table: %w", err)
- }
- return mt, nil
-}
-
-var (
- input = flag.String("input", "", "input disk image (required)")
- output = flag.String("output", "", "output disk image with Verity metadata appended (required)")
- dataDeviceAlias = flag.String("data_alias", "", "data device alias used in the mapping table")
- hashDeviceAlias = flag.String("hash_alias", "", "hash device alias used in the mapping table")
- table = flag.String("table", "", "a file the mapping table will be saved to; disables stdout")
-)
-
-func main() {
- flag.Parse()
-
- // Ensure that required parameters were provided before continuing.
- if *input == "" {
- log.Fatalf("-input must be set.")
- }
- if *output == "" {
- log.Fatalf("-output must be set.")
- }
-
- // Build the image.
- mt, err := createImage(*input, *output, false)
- if err != nil {
- log.Fatal(err)
- }
-
- // Patch the device names, if alternatives were provided.
- if *dataDeviceAlias != "" {
- mt.DataDevicePath = *dataDeviceAlias
- }
- if *hashDeviceAlias != "" {
- mt.HashDevicePath = *hashDeviceAlias
- }
-
- // Print a DeviceMapper target table, or save it to a file, if the table
- // parameter was specified.
- if *table != "" {
- if err := os.WriteFile(*table, []byte(mt.String()), 0644); err != nil {
- log.Fatal(err)
- }
- } else {
- fmt.Println(mt)
- }
-}
diff --git a/metropolis/node/core/abloader/BUILD.bazel b/metropolis/node/core/abloader/BUILD.bazel
index d56a391..e8c49ac 100644
--- a/metropolis/node/core/abloader/BUILD.bazel
+++ b/metropolis/node/core/abloader/BUILD.bazel
@@ -1,5 +1,5 @@
load("@rules_rust//rust:defs.bzl", "rust_binary")
-load("//metropolis/node/build:def.bzl", "platform_transition_binary")
+load("//osbase/build:def.bzl", "platform_transition_binary")
rust_binary(
name = "abloader_bin",
diff --git a/metropolis/node/core/update/BUILD.bazel b/metropolis/node/core/update/BUILD.bazel
index 30ca20b..f60ba40 100644
--- a/metropolis/node/core/update/BUILD.bazel
+++ b/metropolis/node/core/update/BUILD.bazel
@@ -9,9 +9,9 @@
importpath = "source.monogon.dev/metropolis/node/core/update",
visibility = ["//visibility:public"],
deps = [
- "//metropolis/node/build/mkimage/osimage",
"//metropolis/node/core/abloader/spec",
"//osbase/blockdev",
+ "//osbase/build/mkimage/osimage",
"//osbase/efivarfs",
"//osbase/gpt",
"//osbase/kexec",
diff --git a/metropolis/node/core/update/e2e/BUILD.bazel b/metropolis/node/core/update/e2e/BUILD.bazel
index abf3ba1..3443ecf 100644
--- a/metropolis/node/core/update/e2e/BUILD.bazel
+++ b/metropolis/node/core/update/e2e/BUILD.bazel
@@ -26,9 +26,9 @@
"xAbloaderPath": "_main/metropolis/node/core/abloader/abloader_bin.efi",
},
deps = [
- "//metropolis/node/build/mkimage/osimage",
"//osbase/blkio",
"//osbase/blockdev",
+ "//osbase/build/mkimage/osimage",
"@io_bazel_rules_go//go/runfiles:go_default_library",
],
)
diff --git a/metropolis/node/core/update/e2e/e2e_test.go b/metropolis/node/core/update/e2e/e2e_test.go
index 68e55e0..7679a69 100644
--- a/metropolis/node/core/update/e2e/e2e_test.go
+++ b/metropolis/node/core/update/e2e/e2e_test.go
@@ -18,9 +18,9 @@
"github.com/bazelbuild/rules_go/go/runfiles"
- "source.monogon.dev/metropolis/node/build/mkimage/osimage"
"source.monogon.dev/osbase/blkio"
"source.monogon.dev/osbase/blockdev"
+ "source.monogon.dev/osbase/build/mkimage/osimage"
)
var (
diff --git a/metropolis/node/core/update/e2e/testos/BUILD.bazel b/metropolis/node/core/update/e2e/testos/BUILD.bazel
index 275a44c..8a4b122 100644
--- a/metropolis/node/core/update/e2e/testos/BUILD.bazel
+++ b/metropolis/node/core/update/e2e/testos/BUILD.bazel
@@ -13,10 +13,10 @@
importpath = "source.monogon.dev/metropolis/node/core/update/e2e/testos",
visibility = ["//visibility:private"],
deps = [
- "//metropolis/node/build/mkimage/osimage",
"//metropolis/node/core/network",
"//metropolis/node/core/update",
"//osbase/blockdev",
+ "//osbase/build/mkimage/osimage",
"//osbase/gpt",
"//osbase/logtree",
"//osbase/supervisor",
diff --git a/metropolis/node/core/update/e2e/testos/main.go b/metropolis/node/core/update/e2e/testos/main.go
index e77a4e2..69897eb 100644
--- a/metropolis/node/core/update/e2e/testos/main.go
+++ b/metropolis/node/core/update/e2e/testos/main.go
@@ -8,10 +8,10 @@
"golang.org/x/sys/unix"
- "source.monogon.dev/metropolis/node/build/mkimage/osimage"
"source.monogon.dev/metropolis/node/core/network"
"source.monogon.dev/metropolis/node/core/update"
"source.monogon.dev/osbase/blockdev"
+ "source.monogon.dev/osbase/build/mkimage/osimage"
"source.monogon.dev/osbase/gpt"
"source.monogon.dev/osbase/logtree"
"source.monogon.dev/osbase/supervisor"
diff --git a/metropolis/node/core/update/e2e/testos/testos.bzl b/metropolis/node/core/update/e2e/testos/testos.bzl
index 29e218f..2ce3e31 100644
--- a/metropolis/node/core/update/e2e/testos/testos.bzl
+++ b/metropolis/node/core/update/e2e/testos/testos.bzl
@@ -1,6 +1,6 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary")
-load("//metropolis/node/build:def.bzl", "erofs_image", "verity_image")
-load("//metropolis/node/build:efi.bzl", "efi_unified_kernel_image")
+load("//osbase/build:def.bzl", "erofs_image", "verity_image")
+load("//osbase/build:efi.bzl", "efi_unified_kernel_image")
load("@rules_pkg//:pkg.bzl", "pkg_zip")
load("@rules_pkg//:mappings.bzl", "pkg_files")
@@ -14,7 +14,7 @@
"@com_github_coredns_coredns//:coredns": "/kubernetes/bin/coredns",
},
fsspecs = [
- "//metropolis/node/build:earlydev.fsspec",
+ "//osbase/build:earlydev.fsspec",
":rootfs.fsspec",
],
)
diff --git a/metropolis/node/core/update/update.go b/metropolis/node/core/update/update.go
index 28b2381..b6d2ce4 100644
--- a/metropolis/node/core/update/update.go
+++ b/metropolis/node/core/update/update.go
@@ -23,9 +23,9 @@
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
- "source.monogon.dev/metropolis/node/build/mkimage/osimage"
abloaderpb "source.monogon.dev/metropolis/node/core/abloader/spec"
"source.monogon.dev/osbase/blockdev"
+ "source.monogon.dev/osbase/build/mkimage/osimage"
"source.monogon.dev/osbase/efivarfs"
"source.monogon.dev/osbase/gpt"
"source.monogon.dev/osbase/kexec"
diff --git a/metropolis/test/nanoswitch/BUILD.bazel b/metropolis/test/nanoswitch/BUILD.bazel
index 4954480..323d53e 100644
--- a/metropolis/test/nanoswitch/BUILD.bazel
+++ b/metropolis/test/nanoswitch/BUILD.bazel
@@ -1,5 +1,5 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
-load("//metropolis/node/build:def.bzl", "node_initramfs")
+load("//osbase/build:def.bzl", "node_initramfs")
go_library(
name = "nanoswitch_lib",
@@ -42,7 +42,7 @@
"@cacerts//file": "/etc/ssl/cert.pem",
},
fsspecs = [
- "//metropolis/node/build:earlydev.fsspec",
+ "//osbase/build:earlydev.fsspec",
],
visibility = ["//metropolis/test:__subpackages__"],
)
diff --git a/metropolis/vm/smoketest/BUILD.bazel b/metropolis/vm/smoketest/BUILD.bazel
index 7d075d8..6225e2d 100644
--- a/metropolis/vm/smoketest/BUILD.bazel
+++ b/metropolis/vm/smoketest/BUILD.bazel
@@ -1,5 +1,5 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
-load("//metropolis/node/build:def.bzl", "node_initramfs")
+load("//osbase/build:def.bzl", "node_initramfs")
go_library(
name = "smoketest_lib",
@@ -21,7 +21,7 @@
"//metropolis/vm/smoketest/payload": "/init",
},
fsspecs = [
- "//metropolis/node/build:earlydev.fsspec",
+ "//osbase/build:earlydev.fsspec",
],
)