diff options
47 files changed, 4453 insertions, 89 deletions
diff --git a/pkgs/applications/virtualization/crosvm/upstream-info.json b/pkgs/applications/virtualization/crosvm/upstream-info.json deleted file mode 100644 index bb9cc8841b4..00000000000 --- a/pkgs/applications/virtualization/crosvm/upstream-info.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": "81.12871.0.0-rc1", - "components": { - "chromiumos/platform/crosvm": { - "url": "https://chromium.googlesource.com/chromiumos/platform/crosvm", - "rev": "8b8c01e1ad31718932491e4aee63f56109a138e2", - "date": "2020-01-25T02:28:10+00:00", - "sha256": "1qmf1k06pwynh15c3nr9m6v90z2pkk930xniwvlvbvnazrk4rllg", - "fetchSubmodules": false, - "deepClone": false, - "leaveDotGit": false - }, - "chromiumos/third_party/adhd": { - "url": "https://chromium.googlesource.com/chromiumos/third_party/adhd", - "rev": "f361d5b02623274723bff251dafa1e2a2887b013", - "date": "2020-01-23T18:37:46+00:00", - "sha256": "1p8iwjwgmcgmzri03ik2jaid8l0ch0bzn6z9z64dix1hlrvrlliw", - "fetchSubmodules": false, - "deepClone": false, - "leaveDotGit": false - } - } -} diff --git a/pkgs/development/libraries/wlroots/0001-backend-wayland-downgrade-to-wl_compositor-v3.patch b/pkgs/development/libraries/wlroots/0001-backend-wayland-downgrade-to-wl_compositor-v3.patch new file mode 100644 index 00000000000..e6d934419f0 --- /dev/null +++ b/pkgs/development/libraries/wlroots/0001-backend-wayland-downgrade-to-wl_compositor-v3.patch @@ -0,0 +1,84 @@ +From fae720321c2e8e4d57c9c6554d4f025b1808747c Mon Sep 17 00:00:00 2001 +From: Alyssa Ross <hi@alyssa.is> +Date: Tue, 25 Aug 2020 17:34:48 +0000 +Subject: [PATCH 1/2] backend/wayland: downgrade to wl_compositor v3 + +Sommelier does not support v4. + +Rather than calculating exact surface-relative damage regions instead +of the previous buffer-relative ones, just damage the whole surface. +It'll do for now. +--- + backend/wayland/backend.c | 6 +++++- + backend/wayland/output.c | 11 +++++++++-- + include/backend/wayland.h | 1 + + 3 files changed, 15 insertions(+), 3 deletions(-) + +diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c +index 771f4405..fc798292 100644 +--- a/backend/wayland/backend.c ++++ b/backend/wayland/backend.c +@@ -210,7 +210,7 @@ static void registry_global(void *data, struct wl_registry *registry, + + if (strcmp(iface, wl_compositor_interface.name) == 0) { + wl->compositor = wl_registry_bind(registry, name, +- &wl_compositor_interface, 4); ++ &wl_compositor_interface, wl_compositor_version()); + } else if (strcmp(iface, wl_seat_interface.name) == 0) { + struct wl_seat *wl_seat = wl_registry_bind(registry, name, + &wl_seat_interface, 5); +@@ -373,6 +373,10 @@ bool wlr_backend_is_wl(struct wlr_backend *b) { + return b->impl == &backend_impl; + } + ++uint32_t wl_compositor_version(void) { ++ return getenv("SOMMELIER_VERSION") ? 3 : 4; ++} ++ + static void handle_display_destroy(struct wl_listener *listener, void *data) { + struct wlr_wl_backend *wl = + wl_container_of(listener, wl, local_display_destroy); +diff --git a/backend/wayland/output.c b/backend/wayland/output.c +index 542185ce..5c5ff93d 100644 +--- a/backend/wayland/output.c ++++ b/backend/wayland/output.c +@@ -319,7 +319,9 @@ static bool output_commit(struct wlr_output *wlr_output) { + + wl_surface_attach(output->surface, buffer->wl_buffer, 0, 0); + +- if (damage == NULL) { ++ if (wl_compositor_version() < 4) { ++ wl_surface_damage(output->surface, 0, 0, INT32_MAX, INT32_MAX); ++ } else if (damage == NULL) { + wl_surface_damage_buffer(output->surface, + 0, 0, INT32_MAX, INT32_MAX); + } else { +@@ -381,7 +383,12 @@ static bool output_set_cursor(struct wlr_output *wlr_output, + } + + wl_surface_attach(surface, buffer->wl_buffer, 0, 0); +- wl_surface_damage_buffer(surface, 0, 0, INT32_MAX, INT32_MAX); ++ ++ if (wl_compositor_version() < 4) ++ wl_surface_damage(surface, 0, 0, INT32_MAX, INT32_MAX); ++ else ++ wl_surface_damage_buffer(surface, 0, 0, INT32_MAX, INT32_MAX); ++ + wl_surface_commit(surface); + } else { + wl_surface_attach(surface, NULL, 0, 0); +diff --git a/include/backend/wayland.h b/include/backend/wayland.h +index 5d69c248..344dffb1 100644 +--- a/include/backend/wayland.h ++++ b/include/backend/wayland.h +@@ -131,6 +131,7 @@ struct wlr_wl_input_device *create_wl_input_device( + bool create_wl_seat(struct wl_seat *wl_seat, struct wlr_wl_backend *wl); + void destroy_wl_seats(struct wlr_wl_backend *wl); + void destroy_wl_buffer(struct wlr_wl_buffer *buffer); ++uint32_t wl_compositor_version(void); + + extern const struct wl_seat_listener seat_listener; + +-- +2.31.1 + diff --git a/pkgs/development/libraries/wlroots/0002-util-support-virtio_wl-shm-allocation.patch b/pkgs/development/libraries/wlroots/0002-util-support-virtio_wl-shm-allocation.patch new file mode 100644 index 00000000000..cd25aedf35a --- /dev/null +++ b/pkgs/development/libraries/wlroots/0002-util-support-virtio_wl-shm-allocation.patch @@ -0,0 +1,282 @@ +From 8dc7c4e472f6c23e20aee6a7041d260344ffd918 Mon Sep 17 00:00:00 2001 +From: Alyssa Ross <hi@alyssa.is> +Date: Sat, 23 May 2020 03:42:33 +0000 +Subject: [PATCH 2/2] util: support virtio_wl shm allocation + +--- + include/util/virtio_wl.h | 14 ++++++ + include/util/virtio_wl_shm.h | 8 +++ + util/meson.build | 2 + + util/shm.c | 12 +++++ + util/virtio_wl.c | 96 ++++++++++++++++++++++++++++++++++++ + util/virtio_wl_shm.c | 65 ++++++++++++++++++++++++ + 6 files changed, 197 insertions(+) + create mode 100644 include/util/virtio_wl.h + create mode 100644 include/util/virtio_wl_shm.h + create mode 100644 util/virtio_wl.c + create mode 100644 util/virtio_wl_shm.c + +diff --git a/include/util/virtio_wl.h b/include/util/virtio_wl.h +new file mode 100644 +index 00000000..ae5c19b5 +--- /dev/null ++++ b/include/util/virtio_wl.h +@@ -0,0 +1,14 @@ ++#ifndef UTIL_VIRTIO_WL_H ++#define UTIL_VIRTIO_WL_H ++ ++struct virtwl_ioctl_txn; ++ ++int virtio_wl_connect(const char *name, uint32_t flags); ++ ++int32_t virtio_wl_sendmsg(int sockfd, struct virtwl_ioctl_txn *ioctl_txn); ++int32_t virtio_wl_send(int sockfd, const void *buf, uint32_t len); ++ ++int32_t virtio_wl_recvmsg(int sockfd, struct virtwl_ioctl_txn *ioctl_txn); ++int32_t virtio_wl_recv(int sockfd, void *buf, uint32_t len); ++ ++#endif +diff --git a/include/util/virtio_wl_shm.h b/include/util/virtio_wl_shm.h +new file mode 100644 +index 00000000..d9f9f045 +--- /dev/null ++++ b/include/util/virtio_wl_shm.h +@@ -0,0 +1,8 @@ ++#ifndef UTIL_VIRTIO_WL_SHM_H ++#define UTIL_VIRTIO_WL_SHM_H ++ ++#include <stddef.h> ++ ++int allocate_virtio_wl_shm_file(size_t size); ++ ++#endif +diff --git a/util/meson.build b/util/meson.build +index 5e31cbbe..a39cc9bd 100644 +--- a/util/meson.build ++++ b/util/meson.build +@@ -7,5 +7,7 @@ wlr_files += files( + 'signal.c', + 'time.c', + 'token.c', ++ 'virtio_wl.c', ++ 'virtio_wl_shm.c', + ) + +diff --git a/util/shm.c b/util/shm.c +index f7c7303e..d8110904 100644 +--- a/util/shm.c ++++ b/util/shm.c +@@ -2,11 +2,14 @@ + #include <errno.h> + #include <fcntl.h> + #include <string.h> ++#include <stdlib.h> + #include <sys/mman.h> + #include <time.h> + #include <unistd.h> + #include <wlr/config.h> ++#include <wlr/util/log.h> + #include "util/shm.h" ++#include "util/virtio_wl_shm.h" + + static void randname(char *buf) { + struct timespec ts; +@@ -19,6 +22,11 @@ static void randname(char *buf) { + } + + int create_shm_file(void) { ++ if (getenv("WLR_VIRTIO_WL")) { ++ wlr_log(WLR_ERROR, "cannot use create_shm_file with virtio_wl"); ++ return -1; ++ } ++ + int retries = 100; + do { + char name[] = "/wlroots-XXXXXX"; +@@ -37,6 +45,10 @@ int create_shm_file(void) { + } + + int allocate_shm_file(size_t size) { ++ if (getenv("WLR_VIRTIO_WL")) { ++ return allocate_virtio_wl_shm_file(size); ++ } ++ + int fd = create_shm_file(); + if (fd < 0) { + return -1; +diff --git a/util/virtio_wl.c b/util/virtio_wl.c +new file mode 100644 +index 00000000..e7ee58ac +--- /dev/null ++++ b/util/virtio_wl.c +@@ -0,0 +1,96 @@ ++#define _POSIX_C_SOURCE 200809L ++ ++#include <fcntl.h> ++#include <linux/virtwl.h> ++#include <stdint.h> ++#include <string.h> ++#include <sys/ioctl.h> ++#include <stdlib.h> ++#include <unistd.h> ++#include "util/virtio_wl.h" ++ ++// This is essentially vendored reusable library code, so I consider ++// it exempt from the wlroots style guide. :) ++ ++int virtio_wl_connect(const char *name, uint32_t flags) ++{ ++ static int wl_fd = -1; ++ if (wl_fd < 0) ++ wl_fd = open("/dev/wl0", O_RDWR | O_CLOEXEC); ++ if (wl_fd < 0) ++ return wl_fd; ++ ++ struct virtwl_ioctl_new new_ctx = { ++ .type = name ? VIRTWL_IOCTL_NEW_CTX_NAMED : VIRTWL_IOCTL_NEW_CTX, ++ .fd = -1, ++ .flags = flags, ++ }; ++ // Device assumes name 32 bytes long if not null terminated. ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wstringop-truncation" ++ if (name) ++ strncpy(new_ctx.name, name, sizeof(new_ctx.name)); ++#pragma GCC diagnostic pop ++ ++ if (ioctl(wl_fd, VIRTWL_IOCTL_NEW, &new_ctx)) ++ return -1; ++ ++ return new_ctx.fd; ++} ++ ++int32_t virtio_wl_sendmsg(int sockfd, struct virtwl_ioctl_txn *ioctl_txn) ++{ ++ int r = ioctl(sockfd, VIRTWL_IOCTL_SEND, ioctl_txn); ++ if (!r) ++ r = ioctl_txn->len > INT32_MAX ? INT32_MAX : ioctl_txn->len; ++ return r; ++} ++ ++int32_t virtio_wl_send(int sockfd, const void *buf, uint32_t len) ++{ ++ struct virtwl_ioctl_txn *ioctl_txn = malloc(sizeof(*ioctl_txn) + len); ++ if (!ioctl_txn) ++ return -1; ++ ++ for (size_t i = 0; i < VIRTWL_SEND_MAX_ALLOCS; i++) ++ ioctl_txn->fds[i] = -1; ++ ++ ioctl_txn->len = len; ++ memcpy((uint8_t *)ioctl_txn + sizeof(*ioctl_txn), buf, len); ++ ++ int r = virtio_wl_sendmsg(sockfd, ioctl_txn); ++ ++ free(ioctl_txn); ++ return r; ++} ++ ++int32_t virtio_wl_recvmsg(int sockfd, struct virtwl_ioctl_txn *ioctl_txn) ++{ ++ if (ioctl(sockfd, VIRTWL_IOCTL_RECV, ioctl_txn)) ++ return -1; ++ ++ return ioctl_txn->len > INT32_MAX ? INT32_MAX : ioctl_txn->len; ++} ++ ++int32_t virtio_wl_recv(int sockfd, void *buf, uint32_t len) ++{ ++ struct virtwl_ioctl_txn *ioctl_txn = malloc(sizeof(*ioctl_txn) + len); ++ if (!ioctl_txn) ++ return -1; ++ ++ ioctl_txn->len = len; ++ ++ int rv = virtio_wl_recvmsg(sockfd, ioctl_txn); ++ if (rv < 0) ++ goto cleanup; ++ ++ memcpy(buf, (uint8_t *)ioctl_txn + sizeof(*ioctl_txn), ioctl_txn->len); ++ ++ for (size_t i = 0; i < VIRTWL_SEND_MAX_ALLOCS; i++) ++ if (ioctl_txn->fds[i] >= 0) ++ close(ioctl_txn->fds[i]); ++ ++ cleanup: ++ free(ioctl_txn); ++ return rv; ++} +diff --git a/util/virtio_wl_shm.c b/util/virtio_wl_shm.c +new file mode 100644 +index 00000000..b2109310 +--- /dev/null ++++ b/util/virtio_wl_shm.c +@@ -0,0 +1,65 @@ ++#include <assert.h> ++#include <errno.h> ++#include <linux/virtwl.h> ++#include <stdint.h> ++#include <stdlib.h> ++#include <string.h> ++#include "util/virtio_wl.h" ++#include "util/virtio_wl_shm.h" ++ ++// This is essentially vendored reusable library code, so I consider ++// it exempt from the wlroots style guide. :) ++ ++int allocate_virtio_wl_shm_file(size_t size) ++{ ++ static const size_t NAME_SIZE = 224; ++ static const char *NAME = "wlroots"; ++ ++ int r; ++ uint8_t *message = NULL; ++ struct virtwl_ioctl_txn *ioctl_txn = NULL; ++ ++ int conn = virtio_wl_connect("__crosvm_memfd", 0); ++ if (conn < 0) ++ return conn; ++ ++ message = calloc(NAME_SIZE + 8, 1); ++ if (!message) { ++ r = -1; ++ goto cleanup; ++ } ++ strcpy((char *)message, NAME); ++ ++ // Encode size as 64-bit little-endian unsigned integer. ++ for (uint8_t i = 0; i < 8; i++) ++ message[NAME_SIZE + i] = (uint8_t)((uint64_t)size >> (8 * i)); ++ ++ if ((r = virtio_wl_send(conn, message, NAME_SIZE + 8)) < 0) ++ goto cleanup; ++ ++ int32_t len = 1; ++ if (!(ioctl_txn = malloc(sizeof(*ioctl_txn) + len))) { ++ r = -1; ++ goto cleanup; ++ } ++ ioctl_txn->len = len; ++ ++ if ((r = virtio_wl_recvmsg(conn, ioctl_txn)) < 0) ++ goto cleanup; ++ ++ if (((uint8_t *)ioctl_txn + sizeof(*ioctl_txn))[0]) { ++ // We don't actually know why we didn't get the ++ // memory, but out of memory is a reasonable guess. ++ errno = ENOMEM; ++ r = -1; ++ goto cleanup; ++ } ++ ++ r = ioctl_txn->fds[0]; ++ assert(r >= 0); ++ ++ cleanup: ++ free(message); ++ free(ioctl_txn); ++ return r; ++} +-- +2.31.1 + diff --git a/pkgs/development/libraries/wlroots/default.nix b/pkgs/development/libraries/wlroots/default.nix index c22999dd6f0..53117338c13 100644 --- a/pkgs/development/libraries/wlroots/default.nix +++ b/pkgs/development/libraries/wlroots/default.nix @@ -1,7 +1,7 @@ { lib, stdenv, fetchFromGitHub, meson, ninja, pkg-config, wayland-scanner , libGL, wayland, wayland-protocols, libinput, libxkbcommon, pixman , xcbutilwm, libX11, libcap, xcbutilimage, xcbutilerrors, mesa -, libpng, ffmpeg, xcbutilrenderutil, xwayland, seatd +, libpng, ffmpeg, xcbutilrenderutil, xwayland, seatd, linuxHeaders }: stdenv.mkDerivation rec { @@ -15,6 +15,11 @@ stdenv.mkDerivation rec { sha256 = "1sshp3lvlkl1i670kxhwsb4xzxl8raz6769kqvgmxzcb63ns9ay1"; }; + patches = [ + ./0001-backend-wayland-downgrade-to-wl_compositor-v3.patch + ./0002-util-support-virtio_wl-shm-allocation.patch + ]; + # $out for the library and $examples for the example programs (in examples): outputs = [ "out" "examples" ]; @@ -25,7 +30,7 @@ stdenv.mkDerivation rec { buildInputs = [ libGL wayland wayland-protocols libinput libxkbcommon pixman xcbutilwm libX11 libcap xcbutilimage xcbutilerrors mesa - libpng ffmpeg xcbutilrenderutil xwayland seatd + libpng ffmpeg xcbutilrenderutil xwayland seatd linuxHeaders ]; postFixup = '' diff --git a/pkgs/os-specific/linux/chromium-os/common-mk/0001-common-mk-don-t-leak-source-absolute-paths.patch b/pkgs/os-specific/linux/chromium-os/common-mk/0001-common-mk-don-t-leak-source-absolute-paths.patch new file mode 100644 index 00000000000..c2e33dbde66 --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/common-mk/0001-common-mk-don-t-leak-source-absolute-paths.patch @@ -0,0 +1,207 @@ +From ae0c98ed2715c685b0cb97ac6e5d65101168b625 Mon Sep 17 00:00:00 2001 +From: Alyssa Ross <hi@alyssa.is> +Date: Sun, 24 Nov 2019 16:56:11 +0000 +Subject: [PATCH 1/6] common-mk: don't leak source-absolute paths + +Source-absolute paths like //vm_tools/whatever were being leaked to +subprocesses, which of course didn't know how to understand them. +With this patch, source-absolute paths are only used to tell GN the +outputs, and normal Unix paths are passed to subprocesses. +--- + common-mk/external_dependencies/BUILD.gn | 3 ++- + common-mk/mojom_bindings_generator.gni | 12 ++++++------ + common-mk/mojom_type_mappings_generator.gni | 2 +- + common-mk/pkg_config.gni | 3 ++- + common-mk/proto_library.gni | 19 ++++++++++--------- + 5 files changed, 21 insertions(+), 18 deletions(-) + +diff --git a/common-mk/external_dependencies/BUILD.gn b/common-mk/external_dependencies/BUILD.gn +index 2581d31ac8..2ead288006 100644 +--- a/common-mk/external_dependencies/BUILD.gn ++++ b/common-mk/external_dependencies/BUILD.gn +@@ -45,6 +45,7 @@ genxml2cpp("dbus-proxies") { + action("cloud_policy_proto_generator") { + policy_resources_dir = "${sysroot}/usr/share/policy_resources" + proto_out_dir = "${target_gen_dir}/proto" ++ cloud_policy_protobuf_dir = rebase_path(proto_out_dir) + policy_tools_dir = "${sysroot}/usr/share/policy_tools" + + script = "${policy_tools_dir}/generate_policy_source.py" +@@ -54,7 +55,7 @@ action("cloud_policy_proto_generator") { + ] + outputs = [ "${proto_out_dir}/cloud_policy.proto" ] + args = [ +- "--cloud-policy-protobuf=${proto_out_dir}/cloud_policy.proto", ++ "--cloud-policy-protobuf=${cloud_policy_protobuf_dir}/cloud_policy.proto", + "--chrome-version-file=${policy_resources_dir}/VERSION", + "--target-platform=chromeos", + "--policy-templates-file=${policy_resources_dir}/policy_templates.json", +diff --git a/common-mk/mojom_bindings_generator.gni b/common-mk/mojom_bindings_generator.gni +index 038c20ed36..205d7d3037 100644 +--- a/common-mk/mojom_bindings_generator.gni ++++ b/common-mk/mojom_bindings_generator.gni +@@ -100,7 +100,7 @@ template("generate_mojom_bindings_gen") { + args = [ + "mkdir", + "-p", +- mojo_templates_dir, ++ rebase_path(mojo_templates_dir), + ] + } + +@@ -116,7 +116,7 @@ template("generate_mojom_bindings_gen") { + args = [ + "--use_bundled_pylibs", + "-o", +- mojo_templates_dir, ++ rebase_path(mojo_templates_dir), + "precompile", + ] + deps = [ ":${mojo_templates_dir_action_name}" ] +@@ -143,7 +143,7 @@ template("generate_mojom_bindings_gen") { + args = [ + "--mojom-file-list={{response_file_name}}", + "--output-root", +- _mojo_output_base, ++ rebase_path(_mojo_output_base), + "--input-root", + mojo_root, # Mojo depth. + "--input-root", +@@ -188,11 +188,11 @@ template("generate_mojom_bindings_gen") { + mojom_bindings_generator, + "--use_bundled_pylibs", + "--output_dir", +- _mojo_output_base, ++ rebase_path(_mojo_output_base), + "generate", + "--filelist={{response_file_name}}", + "--bytecode_path", +- mojo_templates_dir, ++ rebase_path(mojo_templates_dir), + "-I", + mojo_root, # Mojo include path. + "-d", +@@ -216,7 +216,7 @@ template("generate_mojom_bindings_gen") { + foreach(typemap, invoker.typemaps) { + args += [ + "--typemap", +- typemap, ++ rebase_path(typemap), + ] + } + } +diff --git a/common-mk/mojom_type_mappings_generator.gni b/common-mk/mojom_type_mappings_generator.gni +index ff09397111..959a8b6ca9 100644 +--- a/common-mk/mojom_type_mappings_generator.gni ++++ b/common-mk/mojom_type_mappings_generator.gni +@@ -21,7 +21,7 @@ template("generate_mojom_type_mappings") { + outputs = [ "$target_gen_dir/${target_name}_typemapping" ] + args = [ + "--output", +- "$target_gen_dir/${target_name}_typemapping", ++ rebase_path("$target_gen_dir/${target_name}_typemapping"), + ] + rebase_path(sources, root_build_dir) + } + } +diff --git a/common-mk/pkg_config.gni b/common-mk/pkg_config.gni +index b2c58845d4..31d3f4ab51 100644 +--- a/common-mk/pkg_config.gni ++++ b/common-mk/pkg_config.gni +@@ -81,7 +81,8 @@ template("generate_pkg_config") { + if (!defined(output_name)) { + output_name = name + } +- outputs = [ "${target_out_dir}/${output_name}.pc" ] ++ lib_path = "${target_out_dir}/${output_name}.pc" ++ outputs = [ lib_path ] + + script = "//common-mk/generate-pc.py" + args = [ "--output" ] + rebase_path(outputs) + [ "--name=" + name ] +diff --git a/common-mk/proto_library.gni b/common-mk/proto_library.gni +index e64aedabe0..fb9fb4231d 100644 +--- a/common-mk/proto_library.gni ++++ b/common-mk/proto_library.gni +@@ -56,7 +56,7 @@ template("proto_library") { + + cc_dir = "${root_gen_dir}/${proto_out_dir}" + proto_in_dir = rebase_path(proto_in_dir) +- proto_out_dir = rebase_path(proto_out_dir) ++ proto_out_dir = rebase_path(cc_dir) + + proto_lib_dirs = [ + proto_in_dir, +@@ -96,10 +96,9 @@ template("proto_library") { + } + outputs = [] + if (gen_python) { +- python_dir = "${root_gen_dir}/${proto_out_dir}/py" + args += [ + "--python_out", +- "${python_dir}", ++ "${proto_out_dir}/py", + ] + foreach(source, sources) { + source = rebase_path(source, proto_in_dir) +@@ -109,19 +108,19 @@ template("proto_library") { + } + if (gen_grpc) { + if (gen_grpc_gmock) { +- args += [ "--grpc_out=generate_mock_code=true:${cc_dir}" ] ++ args += [ "--grpc_out=generate_mock_code=true:${proto_out_dir}" ] + foreach(source, sources) { + source = rebase_path(source, proto_in_dir) + source = string_replace(source, ".proto", "") + outputs += [ "${cc_dir}/${source}_mock.grpc.pb.h" ] + } + } else { +- args += [ "--grpc_out=${cc_dir}" ] ++ args += [ "--grpc_out=${proto_out_dir}" ] + } + grpc_cpp_plugin = "/usr/bin/grpc_cpp_plugin" + args += [ + "--plugin=protoc-gen-grpc=${grpc_cpp_plugin}", +- "--cpp_out=${gen_cpp_mode}${cc_dir}", ++ "--cpp_out=${gen_cpp_mode}${proto_out_dir}", + ] + foreach(source, sources) { + source = rebase_path(source, proto_in_dir) +@@ -135,7 +134,7 @@ template("proto_library") { + } + } + if (!gen_grpc && !gen_python) { +- args += [ "--cpp_out=${gen_cpp_mode}${cc_dir}" ] ++ args += [ "--cpp_out=${gen_cpp_mode}${proto_out_dir}" ] + foreach(source, sources) { + source = rebase_path(source, proto_in_dir) + source = string_replace(source, ".proto", "") +@@ -238,7 +237,9 @@ template("goproto_library") { + # otherwise file descriptor var name will conflict. + # cf) https://github.com/golang/protobuf/issues/109 + ++ cc_dir = "${root_gen_dir}/${proto_out_dir}" + proto_in_dir = rebase_path(invoker.proto_in_dir) ++ proto_out_dir = rebase_path(cc_dir) + + # Build protoc command line to run. + script = "//common-mk/file_generator_wrapper.py" +@@ -278,7 +279,7 @@ template("goproto_library") { + "--go_out", + + # go_out_prefix can be empty, so we can always add a colon here. +- "${go_out_prefix}:${root_gen_dir}/${proto_out_dir}", ++ "${go_out_prefix}:${proto_out_dir}", + ] + foreach(source, sources) { + args += [ rebase_path(source) ] +@@ -288,7 +289,7 @@ template("goproto_library") { + outputs = [] + foreach(source, invoker.sources) { + name = get_path_info(source, "name") +- outputs += [ "${root_gen_dir}/${proto_out_dir}/${name}.pb.go" ] ++ outputs += [ "${cc_dir}/${name}.pb.go" ] + } + } + } +-- +2.32.0 + diff --git a/pkgs/os-specific/linux/chromium-os/common-mk/0002-common-mk-.gn-don-t-hardcode-env-path.patch b/pkgs/os-specific/linux/chromium-os/common-mk/0002-common-mk-.gn-don-t-hardcode-env-path.patch new file mode 100644 index 00000000000..a6ac5b1e9ac --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/common-mk/0002-common-mk-.gn-don-t-hardcode-env-path.patch @@ -0,0 +1,23 @@ +From 7d33bcd724ec79d00281c2752f9642be25782370 Mon Sep 17 00:00:00 2001 +From: Alyssa Ross <hi@alyssa.is> +Date: Sun, 24 Nov 2019 17:20:46 +0000 +Subject: [PATCH 2/6] common-mk: .gn: don't hardcode env path + +This is needlessly non-portable. +--- + .gn | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/.gn b/.gn +index e7dba8c91c..e29fcd61ee 100644 +--- a/.gn ++++ b/.gn +@@ -7,4 +7,4 @@ root = "//common-mk/gn_root/:" + + # This makes all scripts run by gn respect the shebang setting of the script. + # Otherwise, the default is to always use `python`. +-script_executable = "/usr/bin/env" ++script_executable = "env" +-- +2.32.0 + diff --git a/pkgs/os-specific/linux/chromium-os/common-mk/default.nix b/pkgs/os-specific/linux/chromium-os/common-mk/default.nix new file mode 100644 index 00000000000..d617401138f --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/common-mk/default.nix @@ -0,0 +1,122 @@ +{ stdenv, lib, fetchFromGitiles, upstreamInfo, gn, pkgconfig, python3, ninja +# , libchrome +}: + +{ platformSubdir + +# Mandatory, unlike in mkDerivation, because Google doesn't provide +# install tasks and just does that in their ebuilds. +, installPhase + +# src allows an out-of-tree (i.e., out-of-platform2) package to be +# built with common-mk. patches will be applied to `src` -- to patch +# platform2 itself use platform2Patches. +, src ? null, platform2Patches ? [] + +# gnArgs allows structured data (attribute sets) to be serialized and +# passed to gn, unlike gnFlags provided by gn's setupHook, which is a +# flat list of strings. +, gnArgs ? {}, gnFlags ? [], use ? {} + +, postUnpack ? "", prePatch ? "", postPatch ? "" +, nativeBuildInputs ? [] +, meta ? {} +, ... } @ args: + +let + platform2 = fetchFromGitiles upstreamInfo.components."src/platform2"; + + attrsToGnList = lib.mapAttrsToList (name: value: "${name}=${toGn value}"); + + toGn = value: + if lib.isAttrs value then + "{${lib.concatStringsSep " " (attrsToGnList value)}}" + else + builtins.toJSON value; +in + +stdenv.mkDerivation ({ + pname = lib.last (lib.splitString "/" platformSubdir); + inherit (upstreamInfo) version; + + srcs = [ platform2 ] ++ lib.optional (src != null) src; + sourceRoot = "platform2"; + + postUnpack = lib.optionalString (src != null) '' + ln -s ../${src.name} $sourceRoot/${platformSubdir} + chmod -R +w ${src.name} + '' + postUnpack; + + prePatch = '' + pushd ${platformSubdir} + '' + prePatch; + + postPatch = '' + popd + ${lib.concatMapStrings (patch: '' + echo applying patch ${patch} + patch -p1 < ${patch} + '') ([ + ./0001-common-mk-don-t-leak-source-absolute-paths.patch + ./0002-common-mk-.gn-don-t-hardcode-env-path.patch + ] ++ platform2Patches)} + + patchShebangs common-mk + '' + (lib.optionalString (!stdenv.cc.isClang) '' + substituteInPlace common-mk/BUILD.gn \ + --replace '"-Wno-c99-designator",' "" \ + --replace '"-Wstring-compare",' "" \ + --replace '"-Wstring-plus-int",' "" \ + --replace '"-Wxor-used-as-pow",' "" \ + --replace '"-Wunreachable-code-return",' "" + '') + postPatch; + + nativeBuildInputs = [ gn pkgconfig python3 ninja ] ++ nativeBuildInputs; + + gnFlags = (attrsToGnList ({ + ar = "ar"; + cc = "cc"; + cxx = "c++"; + # libbase_ver = libchrome.version; + libdir = placeholder "out"; + pkg_config = "pkg-config"; + platform2_root = "."; + platform_subdir = platformSubdir; + use = { + amd64 = stdenv.targetPlatform.isx86_64; + arm = stdenv.targetPlatform.isAarch32 || stdenv.targetPlatform.isAarch64; + asan = false; + coverage = false; + cros_host = false; + crypto = false; + dbus = false; + device_mapper = false; + fuzzer = false; + mojo = false; + profiling = false; + tcmalloc = false; + test = false; + timers = false; + udev = false; + } // use; + } // gnArgs)) ++ gnFlags; + + passthru.updateScript = ../update.py; + + meta = { + homepage = + if src == null then + "${platform2.meta.homepage}/+/HEAD/${platformSubdir}" + else + src.meta.homepage; + platform = lib.platforms.linux; + } // lib.optionalAttrs (src == null) { + license = lib.licenses.bsd3; + } // meta; +} // (builtins.removeAttrs args [ + "src" + "gnArgs" "gnFlags" "use" + "postUnpack" "prePatch" "postPatch" + "nativeBuildInputs" + "meta" +])) diff --git a/pkgs/os-specific/linux/chromium-os/crosvm/VIRTIO_NET_F_MAC.patch b/pkgs/os-specific/linux/chromium-os/crosvm/VIRTIO_NET_F_MAC.patch new file mode 100644 index 00000000000..80cab56b1f8 --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/crosvm/VIRTIO_NET_F_MAC.patch @@ -0,0 +1,278 @@ +From 2b5a83bd9e2c1c9642773c1daf785d03f95f33a3 Mon Sep 17 00:00:00 2001 +From: Alyssa Ross <hi@alyssa.is> +Date: Sun, 27 Sep 2020 15:34:02 +0000 +Subject: [PATCH crosvm v3] crosvm: support setting guest MAC from tap-fd + +This adds a mac= option to crosvm's --tap-fd option. The virtio-net +driver in the guest will read the desired MAC from virtio +configuration space. + +See the documentation for VIRTIO_NET_F_MAC in the Virtio spec[1]. + +[1]: https://docs.oasis-open.org/virtio/virtio/v1.1/virtio-v1.1.html + +Thanks-to: Puck Meerburg <puck@puckipedia.com> +Reviewed-by: Cole Helbling <cole.e.helbling@outlook.com> +Message-Id: <20210517185700.3591932-1-hi@alyssa.is> +--- + devices/src/virtio/net.rs | 20 ++++++++++-- + src/crosvm.rs | 8 +++-- + src/linux.rs | 19 +++++++----- + src/main.rs | 64 +++++++++++++++++++++++++++++++-------- + 4 files changed, 88 insertions(+), 23 deletions(-) + +diff --git a/devices/src/virtio/net.rs b/devices/src/virtio/net.rs +index b88dc44ae..b7489eb2b 100644 +--- a/devices/src/virtio/net.rs ++++ b/devices/src/virtio/net.rs +@@ -419,6 +419,7 @@ where + } + + pub struct Net<T: TapT> { ++ mac_address: Option<MacAddress>, + queue_sizes: Box<[u16]>, + workers_kill_evt: Vec<Event>, + kill_evts: Vec<Event>, +@@ -439,6 +440,7 @@ where + ip_addr: Ipv4Addr, + netmask: Ipv4Addr, + mac_addr: MacAddress, ++ guest_mac_addr: Option<MacAddress>, + vq_pairs: u16, + ) -> Result<Net<T>, NetError> { + let multi_queue = vq_pairs > 1; +@@ -450,12 +452,17 @@ where + + tap.enable().map_err(NetError::TapEnable)?; + +- Net::from(base_features, tap, vq_pairs) ++ Net::with_tap(base_features, tap, vq_pairs, guest_mac_addr) + } + + /// Creates a new virtio network device from a tap device that has already been + /// configured. +- pub fn from(base_features: u64, tap: T, vq_pairs: u16) -> Result<Net<T>, NetError> { ++ pub fn with_tap( ++ base_features: u64, ++ tap: T, ++ vq_pairs: u16, ++ mac_address: Option<MacAddress>, ++ ) -> Result<Net<T>, NetError> { + let taps = tap.into_mq_taps(vq_pairs).map_err(NetError::TapOpen)?; + + // This would also validate a tap created by Self::new(), but that's a good thing as it +@@ -488,7 +495,12 @@ where + workers_kill_evt.push(worker_kill_evt); + } + ++ if mac_address.is_some() { ++ avail_features |= 1 << virtio_net::VIRTIO_NET_F_MAC; ++ } ++ + Ok(Net { ++ mac_address, + queue_sizes: vec![QUEUE_SIZE; (vq_pairs * 2 + 1) as usize].into_boxed_slice(), + workers_kill_evt, + kill_evts, +@@ -503,6 +515,10 @@ where + let vq_pairs = self.queue_sizes.len() as u16 / 2; + + VirtioNetConfig { ++ mac: self ++ .mac_address ++ .map(|m| m.octets()) ++ .unwrap_or_else(Default::default), + max_vq_pairs: Le16::from(vq_pairs), + // Other field has meaningful value when the corresponding feature + // is enabled, but all these features aren't supported now. +diff --git a/src/crosvm.rs b/src/crosvm.rs +index eededc02e..62b3019db 100644 +--- a/src/crosvm.rs ++++ b/src/crosvm.rs +@@ -191,6 +191,10 @@ impl Default for SharedDir { + } + } + ++pub struct TapFdOption { ++ pub mac: Option<net_util::MacAddress>, ++} ++ + /// Aggregate of all configurable options for a running VM. + pub struct Config { + pub kvm_device_path: PathBuf, +@@ -217,7 +221,7 @@ pub struct Config { + pub mac_address: Option<net_util::MacAddress>, + pub net_vq_pairs: Option<u16>, + pub vhost_net: bool, +- pub tap_fd: Vec<RawFd>, ++ pub tap_fd: BTreeMap<RawFd, TapFdOption>, + pub cid: Option<u64>, + pub wayland_socket_paths: BTreeMap<String, PathBuf>, + pub wayland_dmabuf: bool, +@@ -291,7 +295,7 @@ impl Default for Config { + mac_address: None, + net_vq_pairs: None, + vhost_net: false, +- tap_fd: Vec::new(), ++ tap_fd: BTreeMap::new(), + cid: None, + #[cfg(feature = "gpu")] + gpu_parameters: None, +diff --git a/src/linux.rs b/src/linux.rs +index ba2d28f96..e9601478a 100644 +--- a/src/linux.rs ++++ b/src/linux.rs +@@ -60,8 +60,8 @@ use vm_memory::{GuestAddress, GuestMemory}; + #[cfg(all(target_arch = "x86_64", feature = "gdb"))] + use crate::gdb::{gdb_thread, GdbStub}; + use crate::{ +- Config, DiskOption, Executable, SharedDir, SharedDirKind, TouchDeviceOption, VhostUserFsOption, +- VhostUserOption, ++ Config, DiskOption, Executable, SharedDir, SharedDirKind, TapFdOption, TouchDeviceOption, ++ VhostUserFsOption, VhostUserOption, + }; + use arch::{ + self, LinuxArch, RunnableLinuxVm, SerialHardware, SerialParameters, VcpuAffinity, +@@ -763,7 +763,11 @@ fn create_balloon_device(cfg: &Config, tube: Tube) -> DeviceResult { + }) + } + +-fn create_tap_net_device(cfg: &Config, tap_fd: RawDescriptor) -> DeviceResult { ++fn create_tap_net_device( ++ cfg: &Config, ++ tap_fd: RawDescriptor, ++ options: &TapFdOption, ++) -> DeviceResult { + // Safe because we ensure that we get a unique handle to the fd. + let tap = unsafe { + Tap::from_raw_descriptor( +@@ -779,7 +783,8 @@ fn create_tap_net_device(cfg: &Config, tap_fd: RawDescriptor) -> DeviceResult { + vq_pairs = 1; + } + let features = virtio::base_features(cfg.protected_vm); +- let dev = virtio::Net::from(features, tap, vq_pairs).map_err(Error::NetDeviceNew)?; ++ let dev = ++ virtio::Net::with_tap(features, tap, vq_pairs, options.mac).map_err(Error::NetDeviceNew)?; + + Ok(VirtioDeviceStub { + dev: Box::new(dev), +@@ -814,7 +819,7 @@ fn create_net_device( + .map_err(Error::VhostNetDeviceNew)?; + Box::new(dev) as Box<dyn VirtioDevice> + } else { +- let dev = virtio::Net::<Tap>::new(features, host_ip, netmask, mac_address, vq_pairs) ++ let dev = virtio::Net::<Tap>::new(features, host_ip, netmask, mac_address, None, vq_pairs) + .map_err(Error::NetDeviceNew)?; + Box::new(dev) as Box<dyn VirtioDevice> + }; +@@ -1445,8 +1450,8 @@ fn create_virtio_devices( + devs.push(create_balloon_device(cfg, balloon_device_tube)?); + + // We checked above that if the IP is defined, then the netmask is, too. +- for tap_fd in &cfg.tap_fd { +- devs.push(create_tap_net_device(cfg, *tap_fd)?); ++ for (tap_fd, options) in &cfg.tap_fd { ++ devs.push(create_tap_net_device(cfg, *tap_fd, options)?); + } + + if let (Some(host_ip), Some(netmask), Some(mac_address)) = +diff --git a/src/main.rs b/src/main.rs +index ab62f2543..e1188a86c 100644 +--- a/src/main.rs ++++ b/src/main.rs +@@ -20,13 +20,15 @@ use arch::{ + set_default_serial_parameters, Pstore, SerialHardware, SerialParameters, SerialType, + VcpuAffinity, + }; +-use base::{debug, error, getpid, info, kill_process_group, reap_child, syslog, warn}; ++use base::{ ++ debug, error, getpid, info, kill_process_group, reap_child, syslog, warn, RawDescriptor, ++}; + #[cfg(feature = "direct")] + use crosvm::DirectIoOption; + use crosvm::{ + argument::{self, print_help, set_arguments, Argument}, +- platform, BindMount, Config, DiskOption, Executable, GidMap, SharedDir, TouchDeviceOption, +- VhostUserFsOption, VhostUserOption, DISK_ID_LEN, ++ platform, BindMount, Config, DiskOption, Executable, GidMap, SharedDir, TapFdOption, ++ TouchDeviceOption, VhostUserFsOption, VhostUserOption, DISK_ID_LEN, + }; + #[cfg(feature = "gpu")] + use devices::virtio::gpu::{GpuMode, GpuParameters}; +@@ -1460,17 +1462,55 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument:: + } + "vhost-net" => cfg.vhost_net = true, + "tap-fd" => { +- cfg.tap_fd.push( +- value +- .unwrap() +- .parse() +- .map_err(|_| argument::Error::InvalidValue { ++ let mut components = value.unwrap().split(','); ++ ++ let fd: RawDescriptor = ++ components ++ .next() ++ .and_then(|x| x.parse().ok()) ++ .ok_or_else(|| argument::Error::InvalidValue { + value: value.unwrap().to_owned(), + expected: String::from( + "this value for `tap-fd` must be an unsigned integer", + ), +- })?, +- ); ++ })?; ++ ++ let mut mac = None; ++ for c in components { ++ let mut kv = c.splitn(2, '='); ++ let (kind, value) = match (kv.next(), kv.next()) { ++ (Some(kind), Some(value)) => (kind, value), ++ _ => { ++ return Err(argument::Error::InvalidValue { ++ value: c.to_owned(), ++ expected: String::from("option must be of the form `kind=value`"), ++ }) ++ } ++ }; ++ match kind { ++ "mac" => { ++ mac = Some(value.parse().map_err(|_| argument::Error::InvalidValue { ++ value: value.to_owned(), ++ expected: String::from( ++ "`mac` needs to be in the form \"XX:XX:XX:XX:XX:XX\"", ++ ), ++ })?) ++ } ++ _ => { ++ return Err(argument::Error::InvalidValue { ++ value: kind.to_owned(), ++ expected: String::from("unrecognized option"), ++ }) ++ } ++ } ++ } ++ if cfg.tap_fd.contains_key(&fd) { ++ return Err(argument::Error::TooManyArguments(format!( ++ "TAP FD already used: '{}'", ++ name ++ ))); ++ } ++ cfg.tap_fd.insert(fd, TapFdOption { mac }); + } + #[cfg(feature = "gpu")] + "gpu" => { +@@ -1907,8 +1947,8 @@ writeback=BOOL - Indicates whether the VM can use writeback caching (default: fa + Argument::value("plugin-gid-map-file", "PATH", "Path to the file listing supplemental GIDs that should be mapped in plugin jail. Can be given more than once."), + Argument::flag("vhost-net", "Use vhost for networking."), + Argument::value("tap-fd", +- "fd", +- "File descriptor for configured tap device. A different virtual network card will be added each time this argument is given."), ++ "FD[,mac=MAC]", ++ "File descriptor for configured tap device. A different virtual network card will be added each time this argument is given. MAC is the MAC address that will be set in the guest."), + #[cfg(feature = "gpu")] + Argument::flag_or_value("gpu", + "[width=INT,height=INT]", +-- +2.31.1 + diff --git a/pkgs/applications/virtualization/crosvm/default-seccomp-policy-dir.diff b/pkgs/os-specific/linux/chromium-os/crosvm/default-seccomp-policy-dir.diff index f1aa50ee102..f1aa50ee102 100644 --- a/pkgs/applications/virtualization/crosvm/default-seccomp-policy-dir.diff +++ b/pkgs/os-specific/linux/chromium-os/crosvm/default-seccomp-policy-dir.diff diff --git a/pkgs/applications/virtualization/crosvm/default.nix b/pkgs/os-specific/linux/chromium-os/crosvm/default.nix index 697741e21f1..25fa4e2d937 100644 --- a/pkgs/applications/virtualization/crosvm/default.nix +++ b/pkgs/os-specific/linux/chromium-os/crosvm/default.nix @@ -1,26 +1,22 @@ -{ stdenv, lib, rustPlatform, fetchgit, runCommand, symlinkJoin -, pkg-config, minijail, dtc, libusb1, libcap, linux +{ stdenv, lib, rustPlatform, fetchFromGitiles, upstreamInfo +, pkg-config, minigbm, minijail, wayland, wayland-protocols, dtc, libusb1 +, libcap, linux }: let - - upstreamInfo = with builtins; fromJSON (readFile ./upstream-info.json); - arch = with stdenv.hostPlatform; if isAarch64 then "arm" else if isx86_64 then "x86_64" else throw "no seccomp policy files available for host platform"; - crosvmSrc = fetchgit { - inherit (upstreamInfo.components."chromiumos/platform/crosvm") - url rev sha256 fetchSubmodules; - }; - - adhdSrc = fetchgit { - inherit (upstreamInfo.components."chromiumos/third_party/adhd") - url rev sha256 fetchSubmodules; - }; - + getSrc = path: fetchFromGitiles upstreamInfo.components.${path}; + srcs = lib.genAttrs [ + "src/aosp/external/minijail" + "src/platform/crosvm" + "src/platform2" + "src/third_party/adhd" + "src/third_party/rust-vmm/vhost" + ] getSrc; in rustPlatform.buildRustPackage rec { @@ -30,34 +26,30 @@ in unpackPhase = '' runHook preUnpack - mkdir -p chromiumos/platform chromiumos/third_party - - pushd chromiumos/platform - unpackFile ${crosvmSrc} - mv ${crosvmSrc.name} crosvm - popd - - pushd chromiumos/third_party - unpackFile ${adhdSrc} - mv ${adhdSrc.name} adhd - popd + ${lib.concatStringsSep "\n" (lib.mapAttrsToList (path: src: '' + mkdir -p ${dirOf path} + pushd ${dirOf path} + unpackFile ${src} + popd + '') srcs)} chmod -R u+w -- "$sourceRoot" runHook postUnpack ''; - sourceRoot = "chromiumos/platform/crosvm"; + sourceRoot = "src/platform/crosvm"; patches = [ ./default-seccomp-policy-dir.diff + ./VIRTIO_NET_F_MAC.patch ]; - cargoSha256 = "0aax0slg59afbyn3ygswwap2anv11k6sr9hfpysb4f8rvymvx7hd"; + cargoSha256 = "1yhxw19niqwipi1fbrskrpvhs915lrs8sdcpknmqd9izq67r3a06"; - nativeBuildInputs = [ pkg-config ]; + nativeBuildInputs = [ pkg-config wayland ]; - buildInputs = [ dtc libcap libusb1 minijail ]; + buildInputs = [ dtc libcap libusb1 minigbm minijail wayland wayland-protocols ]; postPatch = '' sed -i "s|/usr/share/policy/crosvm/|$out/share/policy/|g" \ @@ -78,9 +70,9 @@ in "${linux}/${stdenv.hostPlatform.linux-kernel.target}"; passthru = { - inherit adhdSrc; - src = crosvmSrc; - updateScript = ./update.py; + inherit srcs; + src = srcs.${sourceRoot}; + updateScript = ../update.py; }; meta = with lib; { diff --git a/pkgs/os-specific/linux/chromium-os/dbus-properties/default.nix b/pkgs/os-specific/linux/chromium-os/dbus-properties/default.nix new file mode 100644 index 00000000000..e95ef4a9aa8 --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/dbus-properties/default.nix @@ -0,0 +1,9 @@ +{ runCommand, chromiumos-overlay }: + +runCommand "dbus-properties" { + passthru.updateScript = ../update.py; +} '' + mkdir -p $out/share/dbus-1/interfaces + cp ${chromiumos-overlay}/sys-apps/dbus/files/org.freedesktop.DBus.Properties.xml \ + $out/share/dbus-1/interfaces +'' diff --git a/pkgs/os-specific/linux/chromium-os/default.nix b/pkgs/os-specific/linux/chromium-os/default.nix new file mode 100644 index 00000000000..efdf600756f --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/default.nix @@ -0,0 +1,64 @@ +{ lib, newScope, fetchFromGitiles, symlinkJoin +, kernelPatches, libqmi, linux_5_4, makeLinuxHeaders, modemmanager +}: + +let + self = with self; { + callPackage = newScope self; + + upstreamInfo = lib.importJSON ./upstream-info.json; + + chromiumos-overlay = (fetchFromGitiles + upstreamInfo.components."src/third_party/chromiumos-overlay") // { + passthru.updateScript = ./update.py; + }; + + common-mk = callPackage ./common-mk { }; + + crosvm = callPackage ./crosvm { }; + + dbus-properties = callPackage ./dbus-properties { }; + + dbus-interfaces = symlinkJoin { + name = "dbus-interfaces"; + paths = [ dbus-properties self.modemmanager modemmanager-next ]; + passthru.updateScript = ./update.py; + }; + + libqmi = callPackage ./libqmi { + inherit libqmi; + }; + + linux_5_4 = callPackage ../kernel/linux-cros.nix { + kernelPatches = + lib.remove kernelPatches.rtl8761b_support linux_5_4.kernelPatches; + }; + + linux = self.linux_5_4; + + linuxHeaders = (makeLinuxHeaders { + inherit (linux) version src patches; + }); + + minigbm = callPackage ./minigbm { }; + + modemmanager = callPackage ./modem-manager { + inherit modemmanager; + }; + + modemmanager-next = callPackage ./modem-manager/next.nix { + inherit modemmanager; + }; + + modp_b64 = callPackage ./modp_b64 { }; + + protofiles = callPackage ./protofiles { }; + + sommelier = callPackage ./sommelier { }; + + vm_protos = callPackage ./vm_protos { }; + }; + +in self // (with self; { + inherit (upstreamInfo) version; +}) diff --git a/pkgs/os-specific/linux/chromium-os/libqmi/default.nix b/pkgs/os-specific/linux/chromium-os/libqmi/default.nix new file mode 100644 index 00000000000..b96b5224b57 --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/libqmi/default.nix @@ -0,0 +1,28 @@ +{ libqmi, lib, fetchFromGitiles, upstreamInfo +, autoreconfHook, autoconf-archive, gtk-doc, docbook-xsl-nons +}: + +libqmi.overrideAttrs ( + { configureFlags ? [], nativeBuildInputs ? [], passthru ? {}, meta ? {}, ... }: + { + pname = "libqmi-unstable"; + version = "2019-12-16"; + + src = fetchFromGitiles upstreamInfo.components."src/third_party/libqmi"; + + nativeBuildInputs = nativeBuildInputs ++ + [ autoreconfHook autoconf-archive gtk-doc docbook-xsl-nons ]; + + # ModemManager tests fail with QRTR in Chromium OS 91. + # Will hopefully be fixed in CrOS 92. + configureFlags = configureFlags ++ [ "--enable-gtk-doc" "--disable-qrtr" ]; + + passthru = passthru // { + updateScript = ../update.py; + }; + + meta = with lib; meta // { + maintainers = with maintainers; [ qyliss ]; + }; + } +) diff --git a/pkgs/os-specific/linux/chromium-os/minigbm/default.nix b/pkgs/os-specific/linux/chromium-os/minigbm/default.nix new file mode 100644 index 00000000000..6c532a4deb2 --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/minigbm/default.nix @@ -0,0 +1,28 @@ +{ stdenv, lib, fetchFromGitiles, upstreamInfo, pkg-config, libdrm }: + +stdenv.mkDerivation { + name = "minigbm"; + inherit (upstreamInfo) version; + + src = fetchFromGitiles upstreamInfo.components."src/platform/minigbm"; + + nativeBuildInputs = [ pkg-config ]; + buildInputs = [ libdrm ]; + + patchPhase = '' + substituteInPlace Makefile --replace /usr/include $out/include + ''; + + buildFlags = [ "ECHO=echo" "PKG_CONFIG=pkg-config" ]; + installFlags = [ "LIBDIR=$(out)/lib" ]; + + enableParallelBuilding = true; + + meta = with lib; { + description = "GBM implementation for Chromium"; + homepage = "https://chromium.googlesource.com/chromiumos/platform/minigbm/"; + maintainers = with maintainers; [ qyliss ]; + license = licenses.bsd3; + platforms = platforms.linux; + }; +} diff --git a/pkgs/os-specific/linux/chromium-os/modem-manager/default.nix b/pkgs/os-specific/linux/chromium-os/modem-manager/default.nix new file mode 100644 index 00000000000..f1d6cbdd465 --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/modem-manager/default.nix @@ -0,0 +1,33 @@ +{ modemmanager, lib, fetchFromGitiles +, autoreconfHook, libtool, intltool, libxslt, dbus_glib, chromiumos-overlay +}: + +modemmanager.overrideAttrs ( + { pname, nativeBuildInputs ? [], buildInputs ? [], postInstall ? "", meta ? {} + , ... }: + { + pname = "${pname}-chromiumos-unstable"; + version = "2012-04-10"; + + src = fetchFromGitiles { + url = "https://chromium.googlesource.com/chromiumos/third_party/modemmanager"; + rev = "657324d1abfd446b0319e4c51bd30cf4967eccf4"; + sha256 = "12wlak8zx914zix4vv5a8sl0nyi58v7593h4gjchgv3i8ysgj9ah"; + }; + + patches = []; + + nativeBuildInputs = nativeBuildInputs ++ [ autoreconfHook libtool intltool libxslt ]; + buildInputs = buildInputs ++ [ dbus_glib ]; + + preAutoreconf = '' + intltoolize + ''; + + NIX_CFLAGS_COMPILE = [ "-Wno-error" ]; + + meta = with lib; meta // { + maintainers = with maintainers; [ qyliss ]; + }; + } +) diff --git a/pkgs/os-specific/linux/chromium-os/modem-manager/next.nix b/pkgs/os-specific/linux/chromium-os/modem-manager/next.nix new file mode 100644 index 00000000000..d008470b682 --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/modem-manager/next.nix @@ -0,0 +1,25 @@ +{ modemmanager, lib, fetchFromGitiles, upstreamInfo +, autoreconfHook, autoconf-archive, gtk-doc, libqmi, libxslt +}: + +(modemmanager.override { inherit libqmi; }).overrideAttrs ( + { pname, nativeBuildInputs ? [], passthru ? {}, meta ? {}, ... }: + { + pname = "${pname}-chromiumos-next-unstable"; + version = "2019-10-17"; + + src = fetchFromGitiles + upstreamInfo.components."src/third_party/modemmanager-next"; + + nativeBuildInputs = nativeBuildInputs ++ + [ autoreconfHook autoconf-archive gtk-doc libxslt ]; + + passthru = passthru // { + updateScript = ../update.py; + }; + + meta = with lib; meta // { + maintainers = with maintainers; [ qyliss ]; + }; + } +) diff --git a/pkgs/os-specific/linux/chromium-os/modp_b64/default.nix b/pkgs/os-specific/linux/chromium-os/modp_b64/default.nix new file mode 100644 index 00000000000..557769336ce --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/modp_b64/default.nix @@ -0,0 +1,23 @@ +{ common-mk, lib, fetchFromGitiles, upstreamInfo }: + +common-mk { + platformSubdir = "modp_b64"; + + src = fetchFromGitiles upstreamInfo.components."src/third_party/modp_b64"; + + installPhase = '' + mkdir -p $out/lib + install -m 0644 libmodp_b64.a $out/lib + + mkdir $out/include + cp -r ../../modp_b64/modp_b64 $out/include + ''; + + meta = with lib; { + description = "High performance base64 encoder/decoder"; + homepage = "https://github.com/client9/stringencoders"; + license = licenses.bsd3; + maintainers = with maintainers; [ qyliss ]; + platform = platforms.all; + }; +} diff --git a/pkgs/os-specific/linux/chromium-os/protofiles/default.nix b/pkgs/os-specific/linux/chromium-os/protofiles/default.nix new file mode 100644 index 00000000000..de8ecbb6963 --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/protofiles/default.nix @@ -0,0 +1,34 @@ +{ stdenv, lib, fetchFromGitiles, chromiumos-overlay, python2 }: + +stdenv.mkDerivation rec { + pname = "protofiles"; + version = "0.0.36"; + + src = fetchFromGitiles { + url = "https://chromium.googlesource.com/chromium/src/components/policy"; + rev = "72e354e16600a8999c85528147dcf762f31a4b78"; + sha256 = "11v7n8d0ma426ba3i6q82k0vj0m5l1hx49waffivplpn0c92bm94"; + }; + + buildInputs = [ python2 ]; + + installPhase = '' + mkdir -p $out/include/proto $out/share/protofiles \ + $out/share/policy_resources $out/share/policy_tools + + install -m 0644 proto/*.proto $out/include/proto + ln -s $out/include/proto/*.proto $out/share/protofiles + install -m 0644 resources/policy_templates.json $out/share/policy_resources + install -m 0644 ${chromiumos-overlay}/chromeos-base/protofiles/files/VERSION \ + $out/share/policy_resources + + install tools/generate_policy_source.py $out/share/policy_tools + ''; + + meta = with lib; { + inherit (src.meta) homepage; + license = licenses.bsd3; + maintainers = with maintainers; [ qyliss ]; + platform = platforms.all; + }; +} diff --git a/pkgs/os-specific/linux/chromium-os/sommelier/0005-sommelier-don-t-leak-source-absolute-paths.patch b/pkgs/os-specific/linux/chromium-os/sommelier/0005-sommelier-don-t-leak-source-absolute-paths.patch new file mode 100644 index 00000000000..d40ff8f022c --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/sommelier/0005-sommelier-don-t-leak-source-absolute-paths.patch @@ -0,0 +1,25 @@ +From 04bdfd44bbaa9f619d3ff03cad3273c46493396e Mon Sep 17 00:00:00 2001 +From: Alyssa Ross <hi@alyssa.is> +Date: Sun, 1 Dec 2019 17:04:04 +0000 +Subject: [PATCH 5/6] sommelier: don't leak source-absolute paths + +--- + vm_tools/sommelier/wayland_protocol.gni | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/vm_tools/sommelier/wayland_protocol.gni b/vm_tools/sommelier/wayland_protocol.gni +index f894adf81d..28bb5a006b 100644 +--- a/vm_tools/sommelier/wayland_protocol.gni ++++ b/vm_tools/sommelier/wayland_protocol.gni +@@ -42,7 +42,7 @@ template("wayland_protocol_library") { + "wayland-scanner", + g.subcommand, + "{{source}}", +- output_file, ++ rebase_path(output_file), + ] + } + } +-- +2.32.0 + diff --git a/pkgs/os-specific/linux/chromium-os/sommelier/0006-Revert-Revert-vm_tools-sommelier-Switch-to-the-stabl.patch b/pkgs/os-specific/linux/chromium-os/sommelier/0006-Revert-Revert-vm_tools-sommelier-Switch-to-the-stabl.patch new file mode 100644 index 00000000000..c7b1eeafc0d --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/sommelier/0006-Revert-Revert-vm_tools-sommelier-Switch-to-the-stabl.patch @@ -0,0 +1,1840 @@ +From e97193872755e44aae51dd88e9323d8a069a40ca Mon Sep 17 00:00:00 2001 +From: Alyssa Ross <hi@alyssa.is> +Date: Fri, 2 Apr 2021 17:55:55 +0000 +Subject: [PATCH 6/6] Revert "Revert "vm_tools: sommelier: Switch to the stable + version of xdg-shell"" + +This reverts commit 32050c0ea6c00c16999915856b40a6a6b8b41bb9. +--- + vm_tools/sommelier/BUILD.gn | 2 +- + vm_tools/sommelier/meson.build | 2 +- + ...dg-shell-unstable-v6.xml => xdg-shell.xml} | 435 +++++++++++++----- + vm_tools/sommelier/sommelier-xdg-shell.cc | 217 +++++---- + vm_tools/sommelier/sommelier.cc | 210 +++++---- + vm_tools/sommelier/sommelier.h | 8 +- + 6 files changed, 535 insertions(+), 339 deletions(-) + rename vm_tools/sommelier/protocol/{xdg-shell-unstable-v6.xml => xdg-shell.xml} (71%) + +diff --git a/vm_tools/sommelier/BUILD.gn b/vm_tools/sommelier/BUILD.gn +index 52df0e3403..fe543138ef 100644 +--- a/vm_tools/sommelier/BUILD.gn ++++ b/vm_tools/sommelier/BUILD.gn +@@ -49,7 +49,7 @@ wayland_protocol_library("sommelier-protocol") { + "protocol/relative-pointer-unstable-v1.xml", + "protocol/text-input-unstable-v1.xml", + "protocol/viewporter.xml", +- "protocol/xdg-shell-unstable-v6.xml", ++ "protocol/xdg-shell.xml", + ] + } + +diff --git a/vm_tools/sommelier/meson.build b/vm_tools/sommelier/meson.build +index 088e3e173f..86bcced912 100644 +--- a/vm_tools/sommelier/meson.build ++++ b/vm_tools/sommelier/meson.build +@@ -58,7 +58,7 @@ wl_protocols = [ + 'protocol/relative-pointer-unstable-v1.xml', + 'protocol/text-input-unstable-v1.xml', + 'protocol/viewporter.xml', +- 'protocol/xdg-shell-unstable-v6.xml', ++ 'protocol/xdg-shell.xml', + ] + + wl_outs = [] +diff --git a/vm_tools/sommelier/protocol/xdg-shell-unstable-v6.xml b/vm_tools/sommelier/protocol/xdg-shell.xml +similarity index 71% +rename from vm_tools/sommelier/protocol/xdg-shell-unstable-v6.xml +rename to vm_tools/sommelier/protocol/xdg-shell.xml +index 1c0f92452b..f7377a713c 100644 +--- a/vm_tools/sommelier/protocol/xdg-shell-unstable-v6.xml ++++ b/vm_tools/sommelier/protocol/xdg-shell.xml +@@ -1,11 +1,13 @@ + <?xml version="1.0" encoding="UTF-8"?> +-<protocol name="xdg_shell_unstable_v6"> ++<protocol name="xdg_shell"> + + <copyright> + Copyright © 2008-2013 Kristian Høgsberg + Copyright © 2013 Rafael Antognolli + Copyright © 2013 Jasper St. Pierre + Copyright © 2010-2013 Intel Corporation ++ Copyright © 2015-2017 Samsung Electronics Co., Ltd ++ Copyright © 2015-2017 Red Hat Inc. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), +@@ -27,18 +29,19 @@ + DEALINGS IN THE SOFTWARE. + </copyright> + +- <interface name="zxdg_shell_v6" version="1"> ++ <interface name="xdg_wm_base" version="3"> + <description summary="create desktop-style surfaces"> +- xdg_shell allows clients to turn a wl_surface into a "real window" +- which can be dragged, resized, stacked, and moved around by the +- user. Everything about this interface is suited towards traditional +- desktop environments. ++ The xdg_wm_base interface is exposed as a global object enabling clients ++ to turn their wl_surfaces into windows in a desktop environment. It ++ defines the basic functionality needed for clients and the compositor to ++ create windows that can be dragged, resized, maximized, etc, as well as ++ creating transient windows such as popup menus. + </description> + + <enum name="error"> + <entry name="role" value="0" summary="given wl_surface has another role"/> + <entry name="defunct_surfaces" value="1" +- summary="xdg_shell was destroyed before children"/> ++ summary="xdg_wm_base was destroyed before children"/> + <entry name="not_the_topmost_popup" value="2" + summary="the client tried to map or destroy a non-topmost popup"/> + <entry name="invalid_popup_parent" value="3" +@@ -50,11 +53,11 @@ + </enum> + + <request name="destroy" type="destructor"> +- <description summary="destroy xdg_shell"> +- Destroy this xdg_shell object. ++ <description summary="destroy xdg_wm_base"> ++ Destroy this xdg_wm_base object. + +- Destroying a bound xdg_shell object while there are surfaces +- still alive created by this xdg_shell object instance is illegal ++ Destroying a bound xdg_wm_base object while there are surfaces ++ still alive created by this xdg_wm_base object instance is illegal + and will result in a protocol error. + </description> + </request> +@@ -65,7 +68,7 @@ + surfaces relative to some parent surface. See the interface description + and xdg_surface.get_popup for details. + </description> +- <arg name="id" type="new_id" interface="zxdg_positioner_v6"/> ++ <arg name="id" type="new_id" interface="xdg_positioner"/> + </request> + + <request name="get_xdg_surface"> +@@ -82,14 +85,14 @@ + See the documentation of xdg_surface for more details about what an + xdg_surface is and how it is used. + </description> +- <arg name="id" type="new_id" interface="zxdg_surface_v6"/> ++ <arg name="id" type="new_id" interface="xdg_surface"/> + <arg name="surface" type="object" interface="wl_surface"/> + </request> + + <request name="pong"> + <description summary="respond to a ping event"> + A client must respond to a ping event with a pong request or +- the client may be deemed unresponsive. See xdg_shell.ping. ++ the client may be deemed unresponsive. See xdg_wm_base.ping. + </description> + <arg name="serial" type="uint" summary="serial of the ping event"/> + </request> +@@ -98,7 +101,7 @@ + <description summary="check if the client is alive"> + The ping event asks the client if it's still alive. Pass the + serial specified in the event back to the compositor by sending +- a "pong" request back with the specified serial. See xdg_shell.ping. ++ a "pong" request back with the specified serial. See xdg_wm_base.pong. + + Compositors can use this to determine if the client is still + alive. It's unspecified what will happen if the client doesn't +@@ -106,13 +109,13 @@ + try to respond in a reasonable amount of time. + + A compositor is free to ping in any way it wants, but a client must +- always respond to any xdg_shell object it created. ++ always respond to any xdg_wm_base object it created. + </description> + <arg name="serial" type="uint" summary="pass this to the pong request"/> + </event> + </interface> + +- <interface name="zxdg_positioner_v6" version="1"> ++ <interface name="xdg_positioner" version="3"> + <description summary="child surface positioner"> + The xdg_positioner provides a collection of rules for the placement of a + child surface relative to a parent surface. Rules can be defined to ensure +@@ -162,13 +165,13 @@ + Specify the anchor rectangle within the parent surface that the child + surface will be placed relative to. The rectangle is relative to the + window geometry as defined by xdg_surface.set_window_geometry of the +- parent surface. The rectangle must be at least 1x1 large. ++ parent surface. + + When the xdg_positioner object is used to position a child surface, the + anchor rectangle may not extend outside the window geometry of the + positioned child's parent surface. + +- If a zero or negative size is set the invalid_input error is raised. ++ If a negative size is set the invalid_input error is raised. + </description> + <arg name="x" type="int" summary="x position of anchor rectangle"/> + <arg name="y" type="int" summary="y position of anchor rectangle"/> +@@ -176,63 +179,54 @@ + <arg name="height" type="int" summary="height of anchor rectangle"/> + </request> + +- <enum name="anchor" bitfield="true"> +- <entry name="none" value="0" +- summary="the center of the anchor rectangle"/> +- <entry name="top" value="1" +- summary="the top edge of the anchor rectangle"/> +- <entry name="bottom" value="2" +- summary="the bottom edge of the anchor rectangle"/> +- <entry name="left" value="4" +- summary="the left edge of the anchor rectangle"/> +- <entry name="right" value="8" +- summary="the right edge of the anchor rectangle"/> ++ <enum name="anchor"> ++ <entry name="none" value="0"/> ++ <entry name="top" value="1"/> ++ <entry name="bottom" value="2"/> ++ <entry name="left" value="3"/> ++ <entry name="right" value="4"/> ++ <entry name="top_left" value="5"/> ++ <entry name="bottom_left" value="6"/> ++ <entry name="top_right" value="7"/> ++ <entry name="bottom_right" value="8"/> + </enum> + + <request name="set_anchor"> +- <description summary="set anchor rectangle anchor edges"> +- Defines a set of edges for the anchor rectangle. These are used to +- derive an anchor point that the child surface will be positioned +- relative to. If two orthogonal edges are specified (e.g. 'top' and +- 'left'), then the anchor point will be the intersection of the edges +- (e.g. the top left position of the rectangle); otherwise, the derived +- anchor point will be centered on the specified edge, or in the center of +- the anchor rectangle if no edge is specified. +- +- If two parallel anchor edges are specified (e.g. 'left' and 'right'), +- the invalid_input error is raised. ++ <description summary="set anchor rectangle anchor"> ++ Defines the anchor point for the anchor rectangle. The specified anchor ++ is used derive an anchor point that the child surface will be ++ positioned relative to. If a corner anchor is set (e.g. 'top_left' or ++ 'bottom_right'), the anchor point will be at the specified corner; ++ otherwise, the derived anchor point will be centered on the specified ++ edge, or in the center of the anchor rectangle if no edge is specified. + </description> + <arg name="anchor" type="uint" enum="anchor" +- summary="bit mask of anchor edges"/> ++ summary="anchor"/> + </request> + +- <enum name="gravity" bitfield="true"> +- <entry name="none" value="0" +- summary="center over the anchor edge"/> +- <entry name="top" value="1" +- summary="position above the anchor edge"/> +- <entry name="bottom" value="2" +- summary="position below the anchor edge"/> +- <entry name="left" value="4" +- summary="position to the left of the anchor edge"/> +- <entry name="right" value="8" +- summary="position to the right of the anchor edge"/> ++ <enum name="gravity"> ++ <entry name="none" value="0"/> ++ <entry name="top" value="1"/> ++ <entry name="bottom" value="2"/> ++ <entry name="left" value="3"/> ++ <entry name="right" value="4"/> ++ <entry name="top_left" value="5"/> ++ <entry name="bottom_left" value="6"/> ++ <entry name="top_right" value="7"/> ++ <entry name="bottom_right" value="8"/> + </enum> + + <request name="set_gravity"> + <description summary="set child surface gravity"> + Defines in what direction a surface should be positioned, relative to +- the anchor point of the parent surface. If two orthogonal gravities are +- specified (e.g. 'bottom' and 'right'), then the child surface will be +- placed in the specified direction; otherwise, the child surface will be +- centered over the anchor point on any axis that had no gravity +- specified. +- +- If two parallel gravities are specified (e.g. 'left' and 'right'), the +- invalid_input error is raised. ++ the anchor point of the parent surface. If a corner gravity is ++ specified (e.g. 'bottom_right' or 'top_left'), then the child surface ++ will be placed towards the specified gravity; otherwise, the child ++ surface will be centered over the anchor point on any axis that had no ++ gravity specified. + </description> + <arg name="gravity" type="uint" enum="gravity" +- summary="bit mask of gravity directions"/> ++ summary="gravity direction"/> + </request> + + <enum name="constraint_adjustment" bitfield="true"> +@@ -252,7 +246,7 @@ + <entry name="none" value="0"> + <description summary="don't move the child surface when constrained"> + Don't alter the surface position even if it is constrained on some +- axis, for example partially outside the edge of a monitor. ++ axis, for example partially outside the edge of an output. + </description> + </entry> + <entry name="slide_x" value="1"> +@@ -304,6 +298,10 @@ + surface is constrained, the gravity is 'bottom' and the anchor is + 'bottom', change the gravity to 'top' and the anchor to 'top'. + ++ The adjusted position is calculated given the original anchor ++ rectangle and offset, but with the new flipped anchor and gravity ++ values. ++ + If the adjusted position also ends up being constrained, the resulting + position of the flip_y adjustment will be the one before the + adjustment. +@@ -359,9 +357,49 @@ + <arg name="x" type="int" summary="surface position x offset"/> + <arg name="y" type="int" summary="surface position y offset"/> + </request> ++ ++ <!-- Version 3 additions --> ++ ++ <request name="set_reactive" since="3"> ++ <description summary="continuously reconstrain the surface"> ++ When set reactive, the surface is reconstrained if the conditions used ++ for constraining changed, e.g. the parent window moved. ++ ++ If the conditions changed and the popup was reconstrained, an ++ xdg_popup.configure event is sent with updated geometry, followed by an ++ xdg_surface.configure event. ++ </description> ++ </request> ++ ++ <request name="set_parent_size" since="3"> ++ <description summary=""> ++ Set the parent window geometry the compositor should use when ++ positioning the popup. The compositor may use this information to ++ determine the future state the popup should be constrained using. If ++ this doesn't match the dimension of the parent the popup is eventually ++ positioned against, the behavior is undefined. ++ ++ The arguments are given in the surface-local coordinate space. ++ </description> ++ <arg name="parent_width" type="int" ++ summary="future window geometry width of parent"/> ++ <arg name="parent_height" type="int" ++ summary="future window geometry height of parent"/> ++ </request> ++ ++ <request name="set_parent_configure" since="3"> ++ <description summary="set parent configure this is a response to"> ++ Set the serial of a xdg_surface.configure event this positioner will be ++ used in response to. The compositor may use this information together ++ with set_parent_size to determine what future state the popup should be ++ constrained using. ++ </description> ++ <arg name="serial" type="uint" ++ summary="serial of parent configure event"/> ++ </request> + </interface> + +- <interface name="zxdg_surface_v6" version="1"> ++ <interface name="xdg_surface" version="3"> + <description summary="desktop user interface surface base interface"> + An interface that may be implemented by a wl_surface, for + implementations that provide a desktop-style user interface. +@@ -388,11 +426,25 @@ + manipulate a buffer prior to the first xdg_surface.configure call must + also be treated as errors. + +- For a surface to be mapped by the compositor, the following conditions +- must be met: (1) the client has assigned a xdg_surface based role to the +- surface, (2) the client has set and committed the xdg_surface state and +- the role dependent state to the surface and (3) the client has committed a +- buffer to the surface. ++ After creating a role-specific object and setting it up, the client must ++ perform an initial commit without any buffer attached. The compositor ++ will reply with an xdg_surface.configure event. The client must ++ acknowledge it and is then allowed to attach a buffer to map the surface. ++ ++ Mapping an xdg_surface-based role surface is defined as making it ++ possible for the surface to be shown by the compositor. Note that ++ a mapped surface is not guaranteed to be visible once it is mapped. ++ ++ For an xdg_surface to be mapped by the compositor, the following ++ conditions must be met: ++ (1) the client has assigned an xdg_surface-based role to the surface ++ (2) the client has set and committed the xdg_surface state and the ++ role-dependent state to the surface ++ (3) the client has committed a buffer to the surface ++ ++ A newly-unmapped surface is considered to have met condition (1) out ++ of the 3 required conditions for mapping a surface if its role surface ++ has not been destroyed. + </description> + + <enum name="error"> +@@ -416,20 +468,23 @@ + See the documentation of xdg_toplevel for more details about what an + xdg_toplevel is and how it is used. + </description> +- <arg name="id" type="new_id" interface="zxdg_toplevel_v6"/> ++ <arg name="id" type="new_id" interface="xdg_toplevel"/> + </request> + + <request name="get_popup"> + <description summary="assign the xdg_popup surface role"> +- This creates an xdg_popup object for the given xdg_surface and gives the +- associated wl_surface the xdg_popup role. ++ This creates an xdg_popup object for the given xdg_surface and gives ++ the associated wl_surface the xdg_popup role. ++ ++ If null is passed as a parent, a parent surface must be specified using ++ some other protocol, before committing the initial state. + + See the documentation of xdg_popup for more details about what an + xdg_popup is and how it is used. + </description> +- <arg name="id" type="new_id" interface="zxdg_popup_v6"/> +- <arg name="parent" type="object" interface="zxdg_surface_v6"/> +- <arg name="positioner" type="object" interface="zxdg_positioner_v6"/> ++ <arg name="id" type="new_id" interface="xdg_popup"/> ++ <arg name="parent" type="object" interface="xdg_surface" allow-null="true"/> ++ <arg name="positioner" type="object" interface="xdg_positioner"/> + </request> + + <request name="set_window_geometry"> +@@ -442,6 +497,11 @@ + The window geometry is double buffered, and will be applied at the + time wl_surface.commit of the corresponding wl_surface is called. + ++ When maintaining a position, the compositor should treat the (x, y) ++ coordinate of the window geometry as the top left corner of the window. ++ A client changing the (x, y) window geometry coordinate should in ++ general not alter the position of the window. ++ + Once the window geometry of the surface is set, it is not possible to + unset it, and it will remain the same until set_window_geometry is + called again, even if a new subsurface or buffer is attached. +@@ -511,36 +571,57 @@ + </description> + <arg name="serial" type="uint" summary="serial of the configure event"/> + </event> ++ + </interface> + +- <interface name="zxdg_toplevel_v6" version="1"> ++ <interface name="xdg_toplevel" version="3"> + <description summary="toplevel surface"> + This interface defines an xdg_surface role which allows a surface to, + among other things, set window-like properties such as maximize, + fullscreen, and minimize, set application-specific metadata like title and + id, and well as trigger user interactive operations such as interactive + resize and move. ++ ++ Unmapping an xdg_toplevel means that the surface cannot be shown ++ by the compositor until it is explicitly mapped again. ++ All active operations (e.g., move, resize) are canceled and all ++ attributes (e.g. title, state, stacking, ...) are discarded for ++ an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to ++ the state it had right after xdg_surface.get_toplevel. The client ++ can re-map the toplevel by perfoming a commit without any buffer ++ attached, waiting for a configure event and handling it as usual (see ++ xdg_surface description). ++ ++ Attaching a null buffer to a toplevel unmaps the surface. + </description> + + <request name="destroy" type="destructor"> + <description summary="destroy the xdg_toplevel"> +- Unmap and destroy the window. The window will be effectively +- hidden from the user's point of view, and all state like +- maximization, fullscreen, and so on, will be lost. ++ This request destroys the role surface and unmaps the surface; ++ see "Unmapping" behavior in interface section for details. + </description> + </request> + + <request name="set_parent"> + <description summary="set the parent of this surface"> +- Set the "parent" of this surface. This window should be stacked +- above a parent. The parent surface must be mapped as long as this +- surface is mapped. ++ Set the "parent" of this surface. This surface should be stacked ++ above the parent surface and all other ancestor surfaces. + + Parent windows should be set on dialogs, toolboxes, or other + "auxiliary" surfaces, so that the parent is raised when the dialog + is raised. ++ ++ Setting a null parent for a child window removes any parent-child ++ relationship for the child. Setting a null parent for a window which ++ currently has no parent is a no-op. ++ ++ If the parent is unmapped then its children are managed as ++ though the parent of the now-unmapped parent has become the ++ parent of this surface. If no parent exists for the now-unmapped ++ parent then the children are managed as though they have no ++ parent surface. + </description> +- <arg name="parent" type="object" interface="zxdg_toplevel_v6" allow-null="true"/> ++ <arg name="parent" type="object" interface="xdg_toplevel" allow-null="true"/> + </request> + + <request name="set_title"> +@@ -573,6 +654,9 @@ + For example, "org.freedesktop.FooViewer" where the .desktop file is + "org.freedesktop.FooViewer.desktop". + ++ Like other properties, a set_app_id request can be sent after the ++ xdg_toplevel has been mapped to update the property. ++ + See the desktop-entry specification [0] for more details on + application identifiers and how they relate to well-known D-Bus + names and .desktop files. +@@ -676,7 +760,7 @@ + </description> + <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/> + <arg name="serial" type="uint" summary="the serial of the user event"/> +- <arg name="edges" type="uint" summary="which edge or corner is being dragged"/> ++ <arg name="edges" type="uint" enum="resize_edge" summary="which edge or corner is being dragged"/> + </request> + + <enum name="state"> +@@ -693,12 +777,18 @@ + <description summary="the surface is maximized"> + The surface is maximized. The window geometry specified in the configure + event must be obeyed by the client. ++ ++ The client should draw without shadow or other ++ decoration outside of the window geometry. + </description> + </entry> + <entry name="fullscreen" value="2" summary="the surface is fullscreen"> + <description summary="the surface is fullscreen"> +- The surface is fullscreen. The window geometry specified in the configure +- event must be obeyed by the client. ++ The surface is fullscreen. The window geometry specified in the ++ configure event is a maximum; the client cannot resize beyond it. For ++ a surface to cover the whole fullscreened area, the geometry ++ dimensions must be obeyed by the client. For more details, see ++ xdg_toplevel.set_fullscreen. + </description> + </entry> + <entry name="resizing" value="3" summary="the surface is being resized"> +@@ -716,6 +806,30 @@ + keyboard or pointer focus. + </description> + </entry> ++ <entry name="tiled_left" value="5" since="2"> ++ <description summary="the surface is tiled"> ++ The window is currently in a tiled layout and the left edge is ++ considered to be adjacent to another part of the tiling grid. ++ </description> ++ </entry> ++ <entry name="tiled_right" value="6" since="2"> ++ <description summary="the surface is tiled"> ++ The window is currently in a tiled layout and the right edge is ++ considered to be adjacent to another part of the tiling grid. ++ </description> ++ </entry> ++ <entry name="tiled_top" value="7" since="2"> ++ <description summary="the surface is tiled"> ++ The window is currently in a tiled layout and the top edge is ++ considered to be adjacent to another part of the tiling grid. ++ </description> ++ </entry> ++ <entry name="tiled_bottom" value="8" since="2"> ++ <description summary="the surface is tiled"> ++ The window is currently in a tiled layout and the bottom edge is ++ considered to be adjacent to another part of the tiling grid. ++ </description> ++ </entry> + </enum> + + <request name="set_max_size"> +@@ -805,12 +919,11 @@ + Maximize the surface. + + After requesting that the surface should be maximized, the compositor +- will respond by emitting a configure event with the "maximized" state +- and the required window geometry. The client should then update its +- content, drawing it in a maximized state, i.e. without shadow or other +- decoration outside of the window geometry. The client must also +- acknowledge the configure when committing the new content (see +- ack_configure). ++ will respond by emitting a configure event. Whether this configure ++ actually sets the window maximized is subject to compositor policies. ++ The client must then update its content, drawing in the configured ++ state. The client must also acknowledge the configure when committing ++ the new content (see ack_configure). + + It is up to the compositor to decide how and where to maximize the + surface, for example which output and what region of the screen should +@@ -818,6 +931,10 @@ + + If the surface was already maximized, the compositor will still emit + a configure event with the "maximized" state. ++ ++ If the surface is in a fullscreen state, this request has no direct ++ effect. It may alter the state the surface is returned to when ++ unmaximized unless overridden by the compositor. + </description> + </request> + +@@ -826,13 +943,13 @@ + Unmaximize the surface. + + After requesting that the surface should be unmaximized, the compositor +- will respond by emitting a configure event without the "maximized" +- state. If available, the compositor will include the window geometry +- dimensions the window had prior to being maximized in the configure +- request. The client must then update its content, drawing it in a +- regular state, i.e. potentially with shadow, etc. The client must also +- acknowledge the configure when committing the new content (see +- ack_configure). ++ will respond by emitting a configure event. Whether this actually ++ un-maximizes the window is subject to compositor policies. ++ If available and applicable, the compositor will include the window ++ geometry dimensions the window had prior to being maximized in the ++ configure event. The client must then update its content, drawing it in ++ the configured state. The client must also acknowledge the configure ++ when committing the new content (see ack_configure). + + It is up to the compositor to position the surface after it was + unmaximized; usually the position the surface had before maximizing, if +@@ -840,24 +957,63 @@ + + If the surface was already not maximized, the compositor will still + emit a configure event without the "maximized" state. ++ ++ If the surface is in a fullscreen state, this request has no direct ++ effect. It may alter the state the surface is returned to when ++ unmaximized unless overridden by the compositor. + </description> + </request> + + <request name="set_fullscreen"> +- <description summary="set the window as fullscreen on a monitor"> ++ <description summary="set the window as fullscreen on an output"> + Make the surface fullscreen. + +- You can specify an output that you would prefer to be fullscreen. +- If this value is NULL, it's up to the compositor to choose which +- display will be used to map this surface. ++ After requesting that the surface should be fullscreened, the ++ compositor will respond by emitting a configure event. Whether the ++ client is actually put into a fullscreen state is subject to compositor ++ policies. The client must also acknowledge the configure when ++ committing the new content (see ack_configure). ++ ++ The output passed by the request indicates the client's preference as ++ to which display it should be set fullscreen on. If this value is NULL, ++ it's up to the compositor to choose which display will be used to map ++ this surface. + + If the surface doesn't cover the whole output, the compositor will + position the surface in the center of the output and compensate with +- black borders filling the rest of the output. ++ with border fill covering the rest of the output. The content of the ++ border fill is undefined, but should be assumed to be in some way that ++ attempts to blend into the surrounding area (e.g. solid black). ++ ++ If the fullscreened surface is not opaque, the compositor must make ++ sure that other screen content not part of the same surface tree (made ++ up of subsurfaces, popups or similarly coupled surfaces) are not ++ visible below the fullscreened surface. + </description> + <arg name="output" type="object" interface="wl_output" allow-null="true"/> + </request> +- <request name="unset_fullscreen" /> ++ ++ <request name="unset_fullscreen"> ++ <description summary="unset the window as fullscreen"> ++ Make the surface no longer fullscreen. ++ ++ After requesting that the surface should be unfullscreened, the ++ compositor will respond by emitting a configure event. ++ Whether this actually removes the fullscreen state of the client is ++ subject to compositor policies. ++ ++ Making a surface unfullscreen sets states for the surface based on the following: ++ * the state(s) it may have had before becoming fullscreen ++ * any state(s) decided by the compositor ++ * any state(s) requested by the client while the surface was fullscreen ++ ++ The compositor may include the previous window geometry dimensions in ++ the configure event, if applicable. ++ ++ The client must also acknowledge the configure when committing the new ++ content (see ack_configure). ++ </description> ++ </request> + + <request name="set_minimized"> + <description summary="set the window as minimized"> +@@ -913,7 +1069,7 @@ + </event> + </interface> + +- <interface name="zxdg_popup_v6" version="1"> ++ <interface name="xdg_popup" version="3"> + <description summary="short-lived, popup surfaces for menus"> + A popup surface is a short-lived, temporary surface. It can be used to + implement for example menus, popovers, tooltips and other similar user +@@ -931,21 +1087,12 @@ + surface of their own is clicked should dismiss the popup using the destroy + request. + +- The parent surface must have either the xdg_toplevel or xdg_popup surface +- role. +- + A newly created xdg_popup will be stacked on top of all previously created + xdg_popup surfaces associated with the same xdg_toplevel. + + The parent of an xdg_popup must be mapped (see the xdg_surface + description) before the xdg_popup itself. + +- The x and y arguments passed when creating the popup object specify +- where the top left of the popup should be placed, relative to the +- local surface coordinates of the parent surface. See +- xdg_surface.get_popup. An xdg_popup must intersect with or be at least +- partially adjacent to its parent surface. +- + The client must call wl_surface.commit on the corresponding wl_surface + for the xdg_popup state to take effect. + </description> +@@ -1023,6 +1170,11 @@ + The x and y arguments represent the position the popup was placed at + given the xdg_positioner rule, relative to the upper left corner of the + window geometry of the parent surface. ++ ++ For version 2 or older, the configure event for an xdg_popup is only ++ ever sent once for the initial configuration. Starting with version 3, ++ it may be sent again if the popup is setup with an xdg_positioner with ++ set_reactive requested, or in response to xdg_popup.reposition requests. + </description> + <arg name="x" type="int" + summary="x position relative to parent surface window geometry"/> +@@ -1040,5 +1192,58 @@ + </description> + </event> + ++ <!-- Version 3 additions --> ++ ++ <request name="reposition" since="3"> ++ <description summary="recalculate the popup's location"> ++ Reposition an already-mapped popup. The popup will be placed given the ++ details in the passed xdg_positioner object, and a ++ xdg_popup.repositioned followed by xdg_popup.configure and ++ xdg_surface.configure will be emitted in response. Any parameters set ++ by the previous positioner will be discarded. ++ ++ The passed token will be sent in the corresponding ++ xdg_popup.repositioned event. The new popup position will not take ++ effect until the corresponding configure event is acknowledged by the ++ client. See xdg_popup.repositioned for details. The token itself is ++ opaque, and has no other special meaning. ++ ++ If multiple reposition requests are sent, the compositor may skip all ++ but the last one. ++ ++ If the popup is repositioned in response to a configure event for its ++ parent, the client should send an xdg_positioner.set_parent_configure ++ and possibly a xdg_positioner.set_parent_size request to allow the ++ compositor to properly constrain the popup. ++ ++ If the popup is repositioned together with a parent that is being ++ resized, but not in response to a configure event, the client should ++ send a xdg_positioner.set_parent_size request. ++ </description> ++ <arg name="positioner" type="object" interface="xdg_positioner"/> ++ <arg name="token" type="uint" summary="reposition request token"/> ++ </request> ++ ++ <event name="repositioned" since="3"> ++ <description summary="signal the completion of a repositioned request"> ++ The repositioned event is sent as part of a popup configuration ++ sequence, together with xdg_popup.configure and lastly ++ xdg_surface.configure to notify the completion of a reposition request. ++ ++ The repositioned event is to notify about the completion of a ++ xdg_popup.reposition request. The token argument is the token passed ++ in the xdg_popup.reposition request. ++ ++ Immediately after this event is emitted, xdg_popup.configure and ++ xdg_surface.configure will be sent with the updated size and position, ++ as well as a new configure serial. ++ ++ The client should optionally update the content of the popup, but must ++ acknowledge the new popup configuration for the new position to take ++ effect. See xdg_surface.ack_configure for details. ++ </description> ++ <arg name="token" type="uint" summary="reposition request token"/> ++ </event> ++ + </interface> + </protocol> +diff --git a/vm_tools/sommelier/sommelier-xdg-shell.cc b/vm_tools/sommelier/sommelier-xdg-shell.cc +index 91744a67e3..45b8eeb93e 100644 +--- a/vm_tools/sommelier/sommelier-xdg-shell.cc ++++ b/vm_tools/sommelier/sommelier-xdg-shell.cc +@@ -7,37 +7,37 @@ + #include <assert.h> + #include <stdlib.h> + +-#include "xdg-shell-unstable-v6-client-protocol.h" // NOLINT(build/include_directory) +-#include "xdg-shell-unstable-v6-server-protocol.h" // NOLINT(build/include_directory) ++#include "xdg-shell-client-protocol.h" // NOLINT(build/include_directory) ++#include "xdg-shell-server-protocol.h" // NOLINT(build/include_directory) + + struct sl_host_xdg_shell { + struct sl_context* ctx; + struct wl_resource* resource; +- struct zxdg_shell_v6* proxy; ++ struct xdg_wm_base* proxy; + }; + + struct sl_host_xdg_surface { + struct sl_context* ctx; + struct wl_resource* resource; +- struct zxdg_surface_v6* proxy; ++ struct xdg_surface* proxy; + }; + + struct sl_host_xdg_toplevel { + struct sl_context* ctx; + struct wl_resource* resource; +- struct zxdg_toplevel_v6* proxy; ++ struct xdg_toplevel* proxy; + }; + + struct sl_host_xdg_popup { + struct sl_context* ctx; + struct wl_resource* resource; +- struct zxdg_popup_v6* proxy; ++ struct xdg_popup* proxy; + }; + + struct sl_host_xdg_positioner { + struct sl_context* ctx; + struct wl_resource* resource; +- struct zxdg_positioner_v6* proxy; ++ struct xdg_positioner* proxy; + }; + + static void sl_xdg_positioner_destroy(struct wl_client* client, +@@ -53,7 +53,7 @@ static void sl_xdg_positioner_set_size(struct wl_client* client, + static_cast<sl_host_xdg_positioner*>(wl_resource_get_user_data(resource)); + double scale = host->ctx->scale; + +- zxdg_positioner_v6_set_size(host->proxy, width / scale, height / scale); ++ xdg_positioner_set_size(host->proxy, width / scale, height / scale); + } + + static void sl_xdg_positioner_set_anchor_rect(struct wl_client* client, +@@ -72,7 +72,7 @@ static void sl_xdg_positioner_set_anchor_rect(struct wl_client* client, + x2 = (x + width) / scale; + y2 = (y + height) / scale; + +- zxdg_positioner_v6_set_anchor_rect(host->proxy, x1, y1, x2 - x1, y2 - y1); ++ xdg_positioner_set_anchor_rect(host->proxy, x1, y1, x2 - x1, y2 - y1); + } + + static void sl_xdg_positioner_set_anchor(struct wl_client* client, +@@ -81,7 +81,7 @@ static void sl_xdg_positioner_set_anchor(struct wl_client* client, + struct sl_host_xdg_positioner* host = + static_cast<sl_host_xdg_positioner*>(wl_resource_get_user_data(resource)); + +- zxdg_positioner_v6_set_anchor(host->proxy, anchor); ++ xdg_positioner_set_anchor(host->proxy, anchor); + } + + static void sl_xdg_positioner_set_gravity(struct wl_client* client, +@@ -90,7 +90,7 @@ static void sl_xdg_positioner_set_gravity(struct wl_client* client, + struct sl_host_xdg_positioner* host = + static_cast<sl_host_xdg_positioner*>(wl_resource_get_user_data(resource)); + +- zxdg_positioner_v6_set_gravity(host->proxy, gravity); ++ xdg_positioner_set_gravity(host->proxy, gravity); + } + + static void sl_xdg_positioner_set_constraint_adjustment( +@@ -100,8 +100,7 @@ static void sl_xdg_positioner_set_constraint_adjustment( + struct sl_host_xdg_positioner* host = + static_cast<sl_host_xdg_positioner*>(wl_resource_get_user_data(resource)); + +- zxdg_positioner_v6_set_constraint_adjustment(host->proxy, +- constraint_adjustment); ++ xdg_positioner_set_constraint_adjustment(host->proxy, constraint_adjustment); + } // NOLINT(whitespace/indent) + + static void sl_xdg_positioner_set_offset(struct wl_client* client, +@@ -112,24 +111,23 @@ static void sl_xdg_positioner_set_offset(struct wl_client* client, + static_cast<sl_host_xdg_positioner*>(wl_resource_get_user_data(resource)); + double scale = host->ctx->scale; + +- zxdg_positioner_v6_set_offset(host->proxy, x / scale, y / scale); ++ xdg_positioner_set_offset(host->proxy, x / scale, y / scale); + } + +-static const struct zxdg_positioner_v6_interface +- sl_xdg_positioner_implementation = { +- sl_xdg_positioner_destroy, +- sl_xdg_positioner_set_size, +- sl_xdg_positioner_set_anchor_rect, +- sl_xdg_positioner_set_anchor, +- sl_xdg_positioner_set_gravity, +- sl_xdg_positioner_set_constraint_adjustment, +- sl_xdg_positioner_set_offset}; ++static const struct xdg_positioner_interface sl_xdg_positioner_implementation = ++ {sl_xdg_positioner_destroy, ++ sl_xdg_positioner_set_size, ++ sl_xdg_positioner_set_anchor_rect, ++ sl_xdg_positioner_set_anchor, ++ sl_xdg_positioner_set_gravity, ++ sl_xdg_positioner_set_constraint_adjustment, ++ sl_xdg_positioner_set_offset}; + + static void sl_destroy_host_xdg_positioner(struct wl_resource* resource) { + struct sl_host_xdg_positioner* host = + static_cast<sl_host_xdg_positioner*>(wl_resource_get_user_data(resource)); + +- zxdg_positioner_v6_destroy(host->proxy); ++ xdg_positioner_destroy(host->proxy); + wl_resource_set_user_data(resource, NULL); + free(host); + } +@@ -148,20 +146,20 @@ static void sl_xdg_popup_grab(struct wl_client* client, + struct sl_host_seat* host_seat = + static_cast<sl_host_seat*>(wl_resource_get_user_data(seat_resource)); + +- zxdg_popup_v6_grab(host->proxy, host_seat->proxy, serial); ++ xdg_popup_grab(host->proxy, host_seat->proxy, serial); + } // NOLINT(whitespace/indent) + +-static const struct zxdg_popup_v6_interface sl_xdg_popup_implementation = { ++static const struct xdg_popup_interface sl_xdg_popup_implementation = { + sl_xdg_popup_destroy, sl_xdg_popup_grab}; + + static void sl_xdg_popup_configure(void* data, +- struct zxdg_popup_v6* xdg_popup, ++ struct xdg_popup* xdg_popup, + int32_t x, + int32_t y, + int32_t width, + int32_t height) { + struct sl_host_xdg_popup* host = +- static_cast<sl_host_xdg_popup*>(zxdg_popup_v6_get_user_data(xdg_popup)); ++ static_cast<sl_host_xdg_popup*>(xdg_popup_get_user_data(xdg_popup)); + double scale = host->ctx->scale; + int32_t x1, y1, x2, y2; + +@@ -170,25 +168,24 @@ static void sl_xdg_popup_configure(void* data, + x2 = (x + width) * scale; + y2 = (y + height) * scale; + +- zxdg_popup_v6_send_configure(host->resource, x1, y1, x2 - x1, y2 - y1); ++ xdg_popup_send_configure(host->resource, x1, y1, x2 - x1, y2 - y1); + } + +-static void sl_xdg_popup_popup_done(void* data, +- struct zxdg_popup_v6* xdg_popup) { ++static void sl_xdg_popup_popup_done(void* data, struct xdg_popup* xdg_popup) { + struct sl_host_xdg_popup* host = +- static_cast<sl_host_xdg_popup*>(zxdg_popup_v6_get_user_data(xdg_popup)); ++ static_cast<sl_host_xdg_popup*>(xdg_popup_get_user_data(xdg_popup)); + +- zxdg_popup_v6_send_popup_done(host->resource); ++ xdg_popup_send_popup_done(host->resource); + } + +-static const struct zxdg_popup_v6_listener sl_xdg_popup_listener = { ++static const struct xdg_popup_listener sl_xdg_popup_listener = { + sl_xdg_popup_configure, sl_xdg_popup_popup_done}; + + static void sl_destroy_host_xdg_popup(struct wl_resource* resource) { + struct sl_host_xdg_popup* host = + static_cast<sl_host_xdg_popup*>(wl_resource_get_user_data(resource)); + +- zxdg_popup_v6_destroy(host->proxy); ++ xdg_popup_destroy(host->proxy); + wl_resource_set_user_data(resource, NULL); + free(host); + } +@@ -208,8 +205,7 @@ static void sl_xdg_toplevel_set_parent(struct wl_client* client, + wl_resource_get_user_data(parent_resource)) + : NULL; + +- zxdg_toplevel_v6_set_parent(host->proxy, +- host_parent ? host_parent->proxy : NULL); ++ xdg_toplevel_set_parent(host->proxy, host_parent ? host_parent->proxy : NULL); + } + + static void sl_xdg_toplevel_set_title(struct wl_client* client, +@@ -218,7 +214,7 @@ static void sl_xdg_toplevel_set_title(struct wl_client* client, + struct sl_host_xdg_toplevel* host = + static_cast<sl_host_xdg_toplevel*>(wl_resource_get_user_data(resource)); + +- zxdg_toplevel_v6_set_title(host->proxy, title); ++ xdg_toplevel_set_title(host->proxy, title); + } + + static void sl_xdg_toplevel_set_app_id(struct wl_client* client, +@@ -227,7 +223,7 @@ static void sl_xdg_toplevel_set_app_id(struct wl_client* client, + struct sl_host_xdg_toplevel* host = + static_cast<sl_host_xdg_toplevel*>(wl_resource_get_user_data(resource)); + +- zxdg_toplevel_v6_set_app_id(host->proxy, app_id); ++ xdg_toplevel_set_app_id(host->proxy, app_id); + } + + static void sl_xdg_toplevel_show_window_menu(struct wl_client* client, +@@ -243,7 +239,7 @@ static void sl_xdg_toplevel_show_window_menu(struct wl_client* client, + ? static_cast<sl_host_seat*>(wl_resource_get_user_data(seat_resource)) + : NULL; + +- zxdg_toplevel_v6_show_window_menu( ++ xdg_toplevel_show_window_menu( + host->proxy, host_seat ? host_seat->proxy : NULL, serial, x, y); + } // NOLINT(whitespace/indent) + +@@ -258,8 +254,7 @@ static void sl_xdg_toplevel_move(struct wl_client* client, + ? static_cast<sl_host_seat*>(wl_resource_get_user_data(seat_resource)) + : NULL; + +- zxdg_toplevel_v6_move(host->proxy, host_seat ? host_seat->proxy : NULL, +- serial); ++ xdg_toplevel_move(host->proxy, host_seat ? host_seat->proxy : NULL, serial); + } // NOLINT(whitespace/indent) + + static void sl_xdg_toplevel_resize(struct wl_client* client, +@@ -274,8 +269,8 @@ static void sl_xdg_toplevel_resize(struct wl_client* client, + ? static_cast<sl_host_seat*>(wl_resource_get_user_data(seat_resource)) + : NULL; + +- zxdg_toplevel_v6_resize(host->proxy, host_seat ? host_seat->proxy : NULL, +- serial, edges); ++ xdg_toplevel_resize(host->proxy, host_seat ? host_seat->proxy : NULL, serial, ++ edges); + } // NOLINT(whitespace/indent) + + static void sl_xdg_toplevel_set_max_size(struct wl_client* client, +@@ -285,7 +280,7 @@ static void sl_xdg_toplevel_set_max_size(struct wl_client* client, + struct sl_host_xdg_toplevel* host = + static_cast<sl_host_xdg_toplevel*>(wl_resource_get_user_data(resource)); + +- zxdg_toplevel_v6_set_max_size(host->proxy, width, height); ++ xdg_toplevel_set_max_size(host->proxy, width, height); + } + + static void sl_xdg_toplevel_set_min_size(struct wl_client* client, +@@ -295,7 +290,7 @@ static void sl_xdg_toplevel_set_min_size(struct wl_client* client, + struct sl_host_xdg_toplevel* host = + static_cast<sl_host_xdg_toplevel*>(wl_resource_get_user_data(resource)); + +- zxdg_toplevel_v6_set_min_size(host->proxy, width, height); ++ xdg_toplevel_set_min_size(host->proxy, width, height); + } + + static void sl_xdg_toplevel_set_maximized(struct wl_client* client, +@@ -303,7 +298,7 @@ static void sl_xdg_toplevel_set_maximized(struct wl_client* client, + struct sl_host_xdg_toplevel* host = + static_cast<sl_host_xdg_toplevel*>(wl_resource_get_user_data(resource)); + +- zxdg_toplevel_v6_set_maximized(host->proxy); ++ xdg_toplevel_set_maximized(host->proxy); + } + + static void sl_xdg_toplevel_unset_maximized(struct wl_client* client, +@@ -311,7 +306,7 @@ static void sl_xdg_toplevel_unset_maximized(struct wl_client* client, + struct sl_host_xdg_toplevel* host = + static_cast<sl_host_xdg_toplevel*>(wl_resource_get_user_data(resource)); + +- zxdg_toplevel_v6_unset_maximized(host->proxy); ++ xdg_toplevel_unset_maximized(host->proxy); + } + + static void sl_xdg_toplevel_set_fullscreen( +@@ -325,8 +320,8 @@ static void sl_xdg_toplevel_set_fullscreen( + wl_resource_get_user_data(output_resource)) + : NULL; + +- zxdg_toplevel_v6_set_fullscreen(host->proxy, +- host_output ? host_output->proxy : NULL); ++ xdg_toplevel_set_fullscreen(host->proxy, ++ host_output ? host_output->proxy : NULL); + } // NOLINT(whitespace/indent) + + static void sl_xdg_toplevel_unset_fullscreen(struct wl_client* client, +@@ -334,7 +329,7 @@ static void sl_xdg_toplevel_unset_fullscreen(struct wl_client* client, + struct sl_host_xdg_toplevel* host = + static_cast<sl_host_xdg_toplevel*>(wl_resource_get_user_data(resource)); + +- zxdg_toplevel_v6_unset_fullscreen(host->proxy); ++ xdg_toplevel_unset_fullscreen(host->proxy); + } + + static void sl_xdg_toplevel_set_minimized(struct wl_client* client, +@@ -342,47 +337,47 @@ static void sl_xdg_toplevel_set_minimized(struct wl_client* client, + struct sl_host_xdg_toplevel* host = + static_cast<sl_host_xdg_toplevel*>(wl_resource_get_user_data(resource)); + +- zxdg_toplevel_v6_set_minimized(host->proxy); ++ xdg_toplevel_set_minimized(host->proxy); + } + +-static const struct zxdg_toplevel_v6_interface sl_xdg_toplevel_implementation = +- {sl_xdg_toplevel_destroy, sl_xdg_toplevel_set_parent, +- sl_xdg_toplevel_set_title, sl_xdg_toplevel_set_app_id, +- sl_xdg_toplevel_show_window_menu, sl_xdg_toplevel_move, +- sl_xdg_toplevel_resize, sl_xdg_toplevel_set_max_size, +- sl_xdg_toplevel_set_min_size, sl_xdg_toplevel_set_maximized, +- sl_xdg_toplevel_unset_maximized, sl_xdg_toplevel_set_fullscreen, +- sl_xdg_toplevel_unset_fullscreen, sl_xdg_toplevel_set_minimized}; ++static const struct xdg_toplevel_interface sl_xdg_toplevel_implementation = { ++ sl_xdg_toplevel_destroy, sl_xdg_toplevel_set_parent, ++ sl_xdg_toplevel_set_title, sl_xdg_toplevel_set_app_id, ++ sl_xdg_toplevel_show_window_menu, sl_xdg_toplevel_move, ++ sl_xdg_toplevel_resize, sl_xdg_toplevel_set_max_size, ++ sl_xdg_toplevel_set_min_size, sl_xdg_toplevel_set_maximized, ++ sl_xdg_toplevel_unset_maximized, sl_xdg_toplevel_set_fullscreen, ++ sl_xdg_toplevel_unset_fullscreen, sl_xdg_toplevel_set_minimized}; + + static void sl_xdg_toplevel_configure(void* data, +- struct zxdg_toplevel_v6* xdg_toplevel, ++ struct xdg_toplevel* xdg_toplevel, + int32_t width, + int32_t height, + struct wl_array* states) { + struct sl_host_xdg_toplevel* host = static_cast<sl_host_xdg_toplevel*>( +- zxdg_toplevel_v6_get_user_data(xdg_toplevel)); ++ xdg_toplevel_get_user_data(xdg_toplevel)); + double scale = host->ctx->scale; + +- zxdg_toplevel_v6_send_configure(host->resource, width * scale, height * scale, +- states); ++ xdg_toplevel_send_configure(host->resource, width * scale, height * scale, ++ states); + } + + static void sl_xdg_toplevel_close(void* data, +- struct zxdg_toplevel_v6* xdg_toplevel) { ++ struct xdg_toplevel* xdg_toplevel) { + struct sl_host_xdg_toplevel* host = static_cast<sl_host_xdg_toplevel*>( +- zxdg_toplevel_v6_get_user_data(xdg_toplevel)); ++ xdg_toplevel_get_user_data(xdg_toplevel)); + +- zxdg_toplevel_v6_send_close(host->resource); ++ xdg_toplevel_send_close(host->resource); + } + +-static const struct zxdg_toplevel_v6_listener sl_xdg_toplevel_listener = { ++static const struct xdg_toplevel_listener sl_xdg_toplevel_listener = { + sl_xdg_toplevel_configure, sl_xdg_toplevel_close}; + + static void sl_destroy_host_xdg_toplevel(struct wl_resource* resource) { + struct sl_host_xdg_toplevel* host = + static_cast<sl_host_xdg_toplevel*>(wl_resource_get_user_data(resource)); + +- zxdg_toplevel_v6_destroy(host->proxy); ++ xdg_toplevel_destroy(host->proxy); + wl_resource_set_user_data(resource, NULL); + free(host); + } +@@ -403,14 +398,14 @@ static void sl_xdg_surface_get_toplevel(struct wl_client* client, + + host_xdg_toplevel->ctx = host->ctx; + host_xdg_toplevel->resource = +- wl_resource_create(client, &zxdg_toplevel_v6_interface, 1, id); ++ wl_resource_create(client, &xdg_toplevel_interface, 1, id); + wl_resource_set_implementation( + host_xdg_toplevel->resource, &sl_xdg_toplevel_implementation, + host_xdg_toplevel, sl_destroy_host_xdg_toplevel); +- host_xdg_toplevel->proxy = zxdg_surface_v6_get_toplevel(host->proxy); +- zxdg_toplevel_v6_set_user_data(host_xdg_toplevel->proxy, host_xdg_toplevel); +- zxdg_toplevel_v6_add_listener(host_xdg_toplevel->proxy, +- &sl_xdg_toplevel_listener, host_xdg_toplevel); ++ host_xdg_toplevel->proxy = xdg_surface_get_toplevel(host->proxy); ++ xdg_toplevel_set_user_data(host_xdg_toplevel->proxy, host_xdg_toplevel); ++ xdg_toplevel_add_listener(host_xdg_toplevel->proxy, &sl_xdg_toplevel_listener, ++ host_xdg_toplevel); + } + + static void sl_xdg_surface_get_popup(struct wl_client* client, +@@ -421,7 +416,7 @@ static void sl_xdg_surface_get_popup(struct wl_client* client, + struct sl_host_xdg_surface* host = + static_cast<sl_host_xdg_surface*>(wl_resource_get_user_data(resource)); + struct sl_host_xdg_surface* host_parent = static_cast<sl_host_xdg_surface*>( +- wl_resource_get_user_data(parent_resource)); ++ parent_resource ? wl_resource_get_user_data(parent_resource) : NULL); + struct sl_host_xdg_positioner* host_positioner = + static_cast<sl_host_xdg_positioner*>( + wl_resource_get_user_data(positioner_resource)); +@@ -431,15 +426,16 @@ static void sl_xdg_surface_get_popup(struct wl_client* client, + + host_xdg_popup->ctx = host->ctx; + host_xdg_popup->resource = +- wl_resource_create(client, &zxdg_popup_v6_interface, 1, id); ++ wl_resource_create(client, &xdg_popup_interface, 1, id); + wl_resource_set_implementation(host_xdg_popup->resource, + &sl_xdg_popup_implementation, host_xdg_popup, + sl_destroy_host_xdg_popup); +- host_xdg_popup->proxy = zxdg_surface_v6_get_popup( +- host->proxy, host_parent->proxy, host_positioner->proxy); +- zxdg_popup_v6_set_user_data(host_xdg_popup->proxy, host_xdg_popup); +- zxdg_popup_v6_add_listener(host_xdg_popup->proxy, &sl_xdg_popup_listener, +- host_xdg_popup); ++ host_xdg_popup->proxy = xdg_surface_get_popup( ++ host->proxy, host_parent ? host_parent->proxy : NULL, ++ host_positioner->proxy); ++ xdg_popup_set_user_data(host_xdg_popup->proxy, host_xdg_popup); ++ xdg_popup_add_listener(host_xdg_popup->proxy, &sl_xdg_popup_listener, ++ host_xdg_popup); + } // NOLINT(whitespace/indent) + + static void sl_xdg_surface_set_window_geometry(struct wl_client* client, +@@ -458,7 +454,7 @@ static void sl_xdg_surface_set_window_geometry(struct wl_client* client, + x2 = (x + width) / scale; + y2 = (y + height) / scale; + +- zxdg_surface_v6_set_window_geometry(host->proxy, x1, y1, x2 - x1, y2 - y1); ++ xdg_surface_set_window_geometry(host->proxy, x1, y1, x2 - x1, y2 - y1); + } + + static void sl_xdg_surface_ack_configure(struct wl_client* client, +@@ -467,31 +463,31 @@ static void sl_xdg_surface_ack_configure(struct wl_client* client, + struct sl_host_xdg_surface* host = + static_cast<sl_host_xdg_surface*>(wl_resource_get_user_data(resource)); + +- zxdg_surface_v6_ack_configure(host->proxy, serial); ++ xdg_surface_ack_configure(host->proxy, serial); + } + +-static const struct zxdg_surface_v6_interface sl_xdg_surface_implementation = { ++static const struct xdg_surface_interface sl_xdg_surface_implementation = { + sl_xdg_surface_destroy, sl_xdg_surface_get_toplevel, + sl_xdg_surface_get_popup, sl_xdg_surface_set_window_geometry, + sl_xdg_surface_ack_configure}; + + static void sl_xdg_surface_configure(void* data, +- struct zxdg_surface_v6* xdg_surface, ++ struct xdg_surface* xdg_surface, + uint32_t serial) { + struct sl_host_xdg_surface* host = static_cast<sl_host_xdg_surface*>( +- zxdg_surface_v6_get_user_data(xdg_surface)); ++ xdg_surface_get_user_data(xdg_surface)); + +- zxdg_surface_v6_send_configure(host->resource, serial); ++ xdg_surface_send_configure(host->resource, serial); + } + +-static const struct zxdg_surface_v6_listener sl_xdg_surface_listener = { ++static const struct xdg_surface_listener sl_xdg_surface_listener = { + sl_xdg_surface_configure}; + + static void sl_destroy_host_xdg_surface(struct wl_resource* resource) { + struct sl_host_xdg_surface* host = + static_cast<sl_host_xdg_surface*>(wl_resource_get_user_data(resource)); + +- zxdg_surface_v6_destroy(host->proxy); ++ xdg_surface_destroy(host->proxy); + wl_resource_set_user_data(resource, NULL); + free(host); + } +@@ -513,13 +509,12 @@ static void sl_xdg_shell_create_positioner(struct wl_client* client, + + host_xdg_positioner->ctx = host->ctx; + host_xdg_positioner->resource = +- wl_resource_create(client, &zxdg_positioner_v6_interface, 1, id); ++ wl_resource_create(client, &xdg_positioner_interface, 1, id); + wl_resource_set_implementation( + host_xdg_positioner->resource, &sl_xdg_positioner_implementation, + host_xdg_positioner, sl_destroy_host_xdg_positioner); +- host_xdg_positioner->proxy = zxdg_shell_v6_create_positioner(host->proxy); +- zxdg_positioner_v6_set_user_data(host_xdg_positioner->proxy, +- host_xdg_positioner); ++ host_xdg_positioner->proxy = xdg_wm_base_create_positioner(host->proxy); ++ xdg_positioner_set_user_data(host_xdg_positioner->proxy, host_xdg_positioner); + } + + static void sl_xdg_shell_get_xdg_surface(struct wl_client* client, +@@ -536,15 +531,15 @@ static void sl_xdg_shell_get_xdg_surface(struct wl_client* client, + + host_xdg_surface->ctx = host->ctx; + host_xdg_surface->resource = +- wl_resource_create(client, &zxdg_surface_v6_interface, 1, id); ++ wl_resource_create(client, &xdg_surface_interface, 1, id); + wl_resource_set_implementation(host_xdg_surface->resource, + &sl_xdg_surface_implementation, + host_xdg_surface, sl_destroy_host_xdg_surface); + host_xdg_surface->proxy = +- zxdg_shell_v6_get_xdg_surface(host->proxy, host_surface->proxy); +- zxdg_surface_v6_set_user_data(host_xdg_surface->proxy, host_xdg_surface); +- zxdg_surface_v6_add_listener(host_xdg_surface->proxy, +- &sl_xdg_surface_listener, host_xdg_surface); ++ xdg_wm_base_get_xdg_surface(host->proxy, host_surface->proxy); ++ xdg_surface_set_user_data(host_xdg_surface->proxy, host_xdg_surface); ++ xdg_surface_add_listener(host_xdg_surface->proxy, &sl_xdg_surface_listener, ++ host_xdg_surface); + host_surface->has_role = 1; + } + +@@ -554,30 +549,30 @@ static void sl_xdg_shell_pong(struct wl_client* client, + struct sl_host_xdg_shell* host = + static_cast<sl_host_xdg_shell*>(wl_resource_get_user_data(resource)); + +- zxdg_shell_v6_pong(host->proxy, serial); ++ xdg_wm_base_pong(host->proxy, serial); + } + +-static const struct zxdg_shell_v6_interface sl_xdg_shell_implementation = { ++static const struct xdg_wm_base_interface sl_xdg_shell_implementation = { + sl_xdg_shell_destroy, sl_xdg_shell_create_positioner, + sl_xdg_shell_get_xdg_surface, sl_xdg_shell_pong}; + + static void sl_xdg_shell_ping(void* data, +- struct zxdg_shell_v6* xdg_shell, ++ struct xdg_wm_base* xdg_shell, + uint32_t serial) { + struct sl_host_xdg_shell* host = +- static_cast<sl_host_xdg_shell*>(zxdg_shell_v6_get_user_data(xdg_shell)); ++ static_cast<sl_host_xdg_shell*>(xdg_wm_base_get_user_data(xdg_shell)); + +- zxdg_shell_v6_send_ping(host->resource, serial); ++ xdg_wm_base_send_ping(host->resource, serial); + } + +-static const struct zxdg_shell_v6_listener sl_xdg_shell_listener = { ++static const struct xdg_wm_base_listener sl_xdg_shell_listener = { + sl_xdg_shell_ping}; + + static void sl_destroy_host_xdg_shell(struct wl_resource* resource) { + struct sl_host_xdg_shell* host = + static_cast<sl_host_xdg_shell*>(wl_resource_get_user_data(resource)); + +- zxdg_shell_v6_destroy(host->proxy); ++ xdg_wm_base_destroy(host->proxy); + wl_resource_set_user_data(resource, NULL); + free(host); + } +@@ -591,17 +586,17 @@ static void sl_bind_host_xdg_shell(struct wl_client* client, + static_cast<sl_host_xdg_shell*>(malloc(sizeof(*host))); + assert(host); + host->ctx = ctx; +- host->resource = wl_resource_create(client, &zxdg_shell_v6_interface, 1, id); ++ host->resource = wl_resource_create(client, &xdg_wm_base_interface, 1, id); + wl_resource_set_implementation(host->resource, &sl_xdg_shell_implementation, + host, sl_destroy_host_xdg_shell); +- host->proxy = static_cast<zxdg_shell_v6*>( ++ host->proxy = static_cast<xdg_wm_base*>( + wl_registry_bind(wl_display_get_registry(ctx->display), +- ctx->xdg_shell->id, &zxdg_shell_v6_interface, 1)); +- zxdg_shell_v6_set_user_data(host->proxy, host); +- zxdg_shell_v6_add_listener(host->proxy, &sl_xdg_shell_listener, host); ++ ctx->xdg_shell->id, &xdg_wm_base_interface, 1)); ++ xdg_wm_base_set_user_data(host->proxy, host); ++ xdg_wm_base_add_listener(host->proxy, &sl_xdg_shell_listener, host); + } + + struct sl_global* sl_xdg_shell_global_create(struct sl_context* ctx) { +- return sl_global_create(ctx, &zxdg_shell_v6_interface, 1, ctx, ++ return sl_global_create(ctx, &xdg_wm_base_interface, 1, ctx, + sl_bind_host_xdg_shell); + } +diff --git a/vm_tools/sommelier/sommelier.cc b/vm_tools/sommelier/sommelier.cc +index 2833e52a61..8f53b3b65b 100644 +--- a/vm_tools/sommelier/sommelier.cc ++++ b/vm_tools/sommelier/sommelier.cc +@@ -39,7 +39,7 @@ + #include "relative-pointer-unstable-v1-client-protocol.h" // NOLINT(build/include_directory) + #include "text-input-unstable-v1-client-protocol.h" // NOLINT(build/include_directory) + #include "viewporter-client-protocol.h" // NOLINT(build/include_directory) +-#include "xdg-shell-unstable-v6-client-protocol.h" // NOLINT(build/include_directory) ++#include "xdg-shell-client-protocol.h" // NOLINT(build/include_directory) + + #define errno_assert(rv) \ + { \ +@@ -372,13 +372,13 @@ void sl_sync_point_destroy(struct sl_sync_point* sync_point) { + } + + static void sl_internal_xdg_shell_ping(void* data, +- struct zxdg_shell_v6* xdg_shell, ++ struct xdg_wm_base* xdg_shell, + uint32_t serial) { + TRACE_EVENT("shell", "sl_internal_xdg_shell_ping"); +- zxdg_shell_v6_pong(xdg_shell, serial); ++ xdg_wm_base_pong(xdg_shell, serial); + } + +-static const struct zxdg_shell_v6_listener sl_internal_xdg_shell_listener = { ++static const struct xdg_wm_base_listener sl_internal_xdg_shell_listener = { + sl_internal_xdg_shell_ping}; + + static void sl_send_configure_notify(struct sl_window* window) { +@@ -549,8 +549,8 @@ int sl_process_pending_configure_acks(struct sl_window* window, + } + + if (window->xdg_surface) { +- zxdg_surface_v6_ack_configure(window->xdg_surface, +- window->pending_config.serial); ++ xdg_surface_ack_configure(window->xdg_surface, ++ window->pending_config.serial); + } + window->pending_config.serial = 0; + +@@ -567,11 +567,12 @@ void sl_commit(struct sl_window* window, struct sl_host_surface* host_surface) { + } + } + +-static void sl_internal_xdg_surface_configure( +- void* data, struct zxdg_surface_v6* xdg_surface, uint32_t serial) { ++static void sl_internal_xdg_surface_configure(void* data, ++ struct xdg_surface* xdg_surface, ++ uint32_t serial) { + TRACE_EVENT("surface", "sl_internal_xdg_surface_configure"); + struct sl_window* window = +- static_cast<sl_window*>(zxdg_surface_v6_get_user_data(xdg_surface)); ++ static_cast<sl_window*>(xdg_surface_get_user_data(xdg_surface)); + + window->next_config.serial = serial; + if (!window->pending_config.serial) { +@@ -589,18 +590,18 @@ static void sl_internal_xdg_surface_configure( + } + } + +-static const struct zxdg_surface_v6_listener sl_internal_xdg_surface_listener = +- {sl_internal_xdg_surface_configure}; ++static const struct xdg_surface_listener sl_internal_xdg_surface_listener = { ++ sl_internal_xdg_surface_configure}; + + static void sl_internal_xdg_toplevel_configure( + void* data, +- struct zxdg_toplevel_v6* xdg_toplevel, ++ struct xdg_toplevel* xdg_toplevel, + int32_t width, + int32_t height, + struct wl_array* states) { + TRACE_EVENT("other", "sl_internal_xdg_toplevel_configure"); + struct sl_window* window = +- static_cast<sl_window*>(zxdg_toplevel_v6_get_user_data(xdg_toplevel)); ++ static_cast<sl_window*>(xdg_toplevel_get_user_data(xdg_toplevel)); + int activated = 0; + uint32_t* state; + int i = 0; +@@ -630,24 +631,24 @@ static void sl_internal_xdg_toplevel_configure( + + window->allow_resize = 1; + sl_array_for_each(state, states) { +- if (*state == ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN) { ++ if (*state == XDG_TOPLEVEL_STATE_FULLSCREEN) { + window->allow_resize = 0; + window->next_config.states[i++] = + window->ctx->atoms[ATOM_NET_WM_STATE_FULLSCREEN].value; + } +- if (*state == ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED) { ++ if (*state == XDG_TOPLEVEL_STATE_MAXIMIZED) { + window->allow_resize = 0; + window->next_config.states[i++] = + window->ctx->atoms[ATOM_NET_WM_STATE_MAXIMIZED_VERT].value; + window->next_config.states[i++] = + window->ctx->atoms[ATOM_NET_WM_STATE_MAXIMIZED_HORZ].value; + } +- if (*state == ZXDG_TOPLEVEL_V6_STATE_ACTIVATED) { ++ if (*state == XDG_TOPLEVEL_STATE_ACTIVATED) { + activated = 1; + window->next_config.states[i++] = + window->ctx->atoms[ATOM_NET_WM_STATE_FOCUSED].value; + } +- if (*state == ZXDG_TOPLEVEL_V6_STATE_RESIZING) ++ if (*state == XDG_TOPLEVEL_STATE_RESIZING) + window->allow_resize = 0; + } + +@@ -662,11 +663,11 @@ static void sl_internal_xdg_toplevel_configure( + window->next_config.states_length = i; + } + +-static void sl_internal_xdg_toplevel_close( +- void* data, struct zxdg_toplevel_v6* xdg_toplevel) { ++static void sl_internal_xdg_toplevel_close(void* data, ++ struct xdg_toplevel* xdg_toplevel) { + TRACE_EVENT("other", "sl_internal_xdg_toplevel_close"); + struct sl_window* window = +- static_cast<sl_window*>(zxdg_toplevel_v6_get_user_data(xdg_toplevel)); ++ static_cast<sl_window*>(xdg_toplevel_get_user_data(xdg_toplevel)); + xcb_client_message_event_t event = {}; + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; +@@ -679,21 +680,20 @@ static void sl_internal_xdg_toplevel_close( + XCB_EVENT_MASK_NO_EVENT, (const char*)&event); + } + +-static const struct zxdg_toplevel_v6_listener +- sl_internal_xdg_toplevel_listener = {sl_internal_xdg_toplevel_configure, +- sl_internal_xdg_toplevel_close}; ++static const struct xdg_toplevel_listener sl_internal_xdg_toplevel_listener = { ++ sl_internal_xdg_toplevel_configure, sl_internal_xdg_toplevel_close}; + + static void sl_internal_xdg_popup_configure(void* data, +- struct zxdg_popup_v6* xdg_popup, ++ struct xdg_popup* xdg_popup, + int32_t x, + int32_t y, + int32_t width, + int32_t height) {} + + static void sl_internal_xdg_popup_done(void* data, +- struct zxdg_popup_v6* zxdg_popup_v6) {} ++ struct xdg_popup* xdg_popup) {} + +-static const struct zxdg_popup_v6_listener sl_internal_xdg_popup_listener = { ++static const struct xdg_popup_listener sl_internal_xdg_popup_listener = { + sl_internal_xdg_popup_configure, sl_internal_xdg_popup_done}; + + static void sl_window_set_wm_state(struct sl_window* window, int state) { +@@ -765,15 +765,15 @@ void sl_window_update(struct sl_window* window) { + window->aura_surface = NULL; + } + if (window->xdg_toplevel) { +- zxdg_toplevel_v6_destroy(window->xdg_toplevel); ++ xdg_toplevel_destroy(window->xdg_toplevel); + window->xdg_toplevel = NULL; + } + if (window->xdg_popup) { +- zxdg_popup_v6_destroy(window->xdg_popup); ++ xdg_popup_destroy(window->xdg_popup); + window->xdg_popup = NULL; + } + if (window->xdg_surface) { +- zxdg_surface_v6_destroy(window->xdg_surface); ++ xdg_surface_destroy(window->xdg_surface); + window->xdg_surface = NULL; + } + window->realized = 0; +@@ -849,11 +849,11 @@ void sl_window_update(struct sl_window* window) { + } + + if (!window->xdg_surface) { +- window->xdg_surface = zxdg_shell_v6_get_xdg_surface( +- ctx->xdg_shell->internal, host_surface->proxy); +- zxdg_surface_v6_set_user_data(window->xdg_surface, window); +- zxdg_surface_v6_add_listener(window->xdg_surface, +- &sl_internal_xdg_surface_listener, window); ++ window->xdg_surface = xdg_wm_base_get_xdg_surface(ctx->xdg_shell->internal, ++ host_surface->proxy); ++ xdg_surface_set_user_data(window->xdg_surface, window); ++ xdg_surface_add_listener(window->xdg_surface, ++ &sl_internal_xdg_surface_listener, window); + } + + if (ctx->aura_shell) { +@@ -888,50 +888,46 @@ void sl_window_update(struct sl_window* window) { + // window is closed. + if (ctx->xwayland || !parent) { + if (!window->xdg_toplevel) { +- window->xdg_toplevel = zxdg_surface_v6_get_toplevel(window->xdg_surface); +- zxdg_toplevel_v6_set_user_data(window->xdg_toplevel, window); +- zxdg_toplevel_v6_add_listener(window->xdg_toplevel, +- &sl_internal_xdg_toplevel_listener, window); ++ window->xdg_toplevel = xdg_surface_get_toplevel(window->xdg_surface); ++ xdg_toplevel_set_user_data(window->xdg_toplevel, window); ++ xdg_toplevel_add_listener(window->xdg_toplevel, ++ &sl_internal_xdg_toplevel_listener, window); + } + if (parent) +- zxdg_toplevel_v6_set_parent(window->xdg_toplevel, parent->xdg_toplevel); ++ xdg_toplevel_set_parent(window->xdg_toplevel, parent->xdg_toplevel); + if (window->name) +- zxdg_toplevel_v6_set_title(window->xdg_toplevel, window->name); ++ xdg_toplevel_set_title(window->xdg_toplevel, window->name); + if (window->size_flags & P_MIN_SIZE) { +- zxdg_toplevel_v6_set_min_size(window->xdg_toplevel, +- window->min_width / ctx->scale, +- window->min_height / ctx->scale); ++ xdg_toplevel_set_min_size(window->xdg_toplevel, ++ window->min_width / ctx->scale, ++ window->min_height / ctx->scale); + } + if (window->size_flags & P_MAX_SIZE) { +- zxdg_toplevel_v6_set_max_size(window->xdg_toplevel, +- window->max_width / ctx->scale, +- window->max_height / ctx->scale); ++ xdg_toplevel_set_max_size(window->xdg_toplevel, ++ window->max_width / ctx->scale, ++ window->max_height / ctx->scale); + } + if (window->maximized) { +- zxdg_toplevel_v6_set_maximized(window->xdg_toplevel); ++ xdg_toplevel_set_maximized(window->xdg_toplevel); + } + } else if (!window->xdg_popup) { +- struct zxdg_positioner_v6* positioner; ++ struct xdg_positioner* positioner; + +- positioner = zxdg_shell_v6_create_positioner(ctx->xdg_shell->internal); ++ positioner = xdg_wm_base_create_positioner(ctx->xdg_shell->internal); + assert(positioner); +- zxdg_positioner_v6_set_anchor( +- positioner, +- ZXDG_POSITIONER_V6_ANCHOR_TOP | ZXDG_POSITIONER_V6_ANCHOR_LEFT); +- zxdg_positioner_v6_set_gravity( +- positioner, +- ZXDG_POSITIONER_V6_GRAVITY_BOTTOM | ZXDG_POSITIONER_V6_GRAVITY_RIGHT); +- zxdg_positioner_v6_set_anchor_rect( +- positioner, (window->x - parent->x) / ctx->scale, +- (window->y - parent->y) / ctx->scale, 1, 1); ++ xdg_positioner_set_anchor(positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT); ++ xdg_positioner_set_gravity(positioner, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT); ++ xdg_positioner_set_anchor_rect(positioner, ++ (window->x - parent->x) / ctx->scale, ++ (window->y - parent->y) / ctx->scale, 1, 1); + +- window->xdg_popup = zxdg_surface_v6_get_popup( +- window->xdg_surface, parent->xdg_surface, positioner); +- zxdg_popup_v6_set_user_data(window->xdg_popup, window); +- zxdg_popup_v6_add_listener(window->xdg_popup, +- &sl_internal_xdg_popup_listener, window); ++ window->xdg_popup = xdg_surface_get_popup(window->xdg_surface, ++ parent->xdg_surface, positioner); ++ xdg_popup_set_user_data(window->xdg_popup, window); ++ xdg_popup_add_listener(window->xdg_popup, &sl_internal_xdg_popup_listener, ++ window); + +- zxdg_positioner_v6_destroy(positioner); ++ xdg_positioner_destroy(positioner); + } + + if ((window->size_flags & (US_POSITION | P_POSITION)) && parent && +@@ -1332,7 +1328,7 @@ static void sl_registry_handler(void* data, + data_device_manager->host_global = + sl_data_device_manager_global_create(ctx); + } +- } else if (strcmp(interface, "zxdg_shell_v6") == 0) { ++ } else if (strcmp(interface, "xdg_wm_base") == 0) { + struct sl_xdg_shell* xdg_shell = + static_cast<sl_xdg_shell*>(malloc(sizeof(struct sl_xdg_shell))); + assert(xdg_shell); +@@ -1343,10 +1339,10 @@ static void sl_registry_handler(void* data, + assert(!ctx->xdg_shell); + ctx->xdg_shell = xdg_shell; + if (ctx->xwayland) { +- xdg_shell->internal = static_cast<zxdg_shell_v6*>( +- wl_registry_bind(registry, id, &zxdg_shell_v6_interface, 1)); +- zxdg_shell_v6_add_listener(xdg_shell->internal, +- &sl_internal_xdg_shell_listener, NULL); ++ xdg_shell->internal = static_cast<xdg_wm_base*>( ++ wl_registry_bind(registry, id, &xdg_wm_base_interface, 1)); ++ xdg_wm_base_add_listener(xdg_shell->internal, ++ &sl_internal_xdg_shell_listener, NULL); + } else { + xdg_shell->host_global = sl_xdg_shell_global_create(ctx); + } +@@ -1479,7 +1475,7 @@ static void sl_registry_remover(void* data, + if (ctx->xdg_shell->host_global) + sl_global_destroy(ctx->xdg_shell->host_global); + if (ctx->xdg_shell->internal) +- zxdg_shell_v6_destroy(ctx->xdg_shell->internal); ++ xdg_wm_base_destroy(ctx->xdg_shell->internal); + free(ctx->xdg_shell); + ctx->xdg_shell = NULL; + return; +@@ -1656,11 +1652,11 @@ static void sl_destroy_window(struct sl_window* window) { + } + + if (window->xdg_popup) +- zxdg_popup_v6_destroy(window->xdg_popup); ++ xdg_popup_destroy(window->xdg_popup); + if (window->xdg_toplevel) +- zxdg_toplevel_v6_destroy(window->xdg_toplevel); ++ xdg_toplevel_destroy(window->xdg_toplevel); + if (window->xdg_surface) +- zxdg_surface_v6_destroy(window->xdg_surface); ++ xdg_surface_destroy(window->xdg_surface); + if (window->aura_surface) + zaura_surface_destroy(window->aura_surface); + +@@ -2124,15 +2120,15 @@ static void sl_handle_configure_request(struct sl_context* ctx, + // that matching contents will arrive. + if (window->xdg_toplevel) { + if (window->pending_config.serial) { +- zxdg_surface_v6_ack_configure(window->xdg_surface, +- window->pending_config.serial); ++ xdg_surface_ack_configure(window->xdg_surface, ++ window->pending_config.serial); + window->pending_config.serial = 0; + window->pending_config.mask = 0; + window->pending_config.states_length = 0; + } + if (window->next_config.serial) { +- zxdg_surface_v6_ack_configure(window->xdg_surface, +- window->next_config.serial); ++ xdg_surface_ack_configure(window->xdg_surface, ++ window->next_config.serial); + window->next_config.serial = 0; + window->next_config.mask = 0; + window->next_config.states_length = 0; +@@ -2253,23 +2249,23 @@ static void sl_handle_configure_notify(struct sl_context* ctx, + static uint32_t sl_resize_edge(int net_wm_moveresize_size) { + switch (net_wm_moveresize_size) { + case NET_WM_MOVERESIZE_SIZE_TOPLEFT: +- return ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_LEFT; ++ return XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; + case NET_WM_MOVERESIZE_SIZE_TOP: +- return ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP; ++ return XDG_TOPLEVEL_RESIZE_EDGE_TOP; + case NET_WM_MOVERESIZE_SIZE_TOPRIGHT: +- return ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_RIGHT; ++ return XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; + case NET_WM_MOVERESIZE_SIZE_RIGHT: +- return ZXDG_TOPLEVEL_V6_RESIZE_EDGE_RIGHT; ++ return XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; + case NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT: +- return ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_RIGHT; ++ return XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; + case NET_WM_MOVERESIZE_SIZE_BOTTOM: +- return ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM; ++ return XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; + case NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT: +- return ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_LEFT; ++ return XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; + case NET_WM_MOVERESIZE_SIZE_LEFT: +- return ZXDG_TOPLEVEL_V6_RESIZE_EDGE_LEFT; ++ return XDG_TOPLEVEL_RESIZE_EDGE_LEFT; + default: +- return ZXDG_TOPLEVEL_V6_RESIZE_EDGE_NONE; ++ return XDG_TOPLEVEL_RESIZE_EDGE_NONE; + } + } + +@@ -2368,16 +2364,16 @@ static void sl_handle_client_message(struct sl_context* ctx, + return; + + if (event->data.data32[2] == NET_WM_MOVERESIZE_MOVE) { +- zxdg_toplevel_v6_move(window->xdg_toplevel, seat->proxy, +- seat->seat->last_serial); ++ xdg_toplevel_move(window->xdg_toplevel, seat->proxy, ++ seat->seat->last_serial); + } else { + uint32_t edge = sl_resize_edge(event->data.data32[2]); + +- if (edge == ZXDG_TOPLEVEL_V6_RESIZE_EDGE_NONE) ++ if (edge == XDG_TOPLEVEL_RESIZE_EDGE_NONE) + return; + +- zxdg_toplevel_v6_resize(window->xdg_toplevel, seat->proxy, +- seat->seat->last_serial, edge); ++ xdg_toplevel_resize(window->xdg_toplevel, seat->proxy, ++ seat->seat->last_serial, edge); + } + } + } else if (event->type == ctx->atoms[ATOM_NET_WM_STATE].value) { +@@ -2398,9 +2394,9 @@ static void sl_handle_client_message(struct sl_context* ctx, + "action", net_wm_state_to_string(action), "window->name", + window->name); + if (action == NET_WM_STATE_ADD) +- zxdg_toplevel_v6_set_fullscreen(window->xdg_toplevel, NULL); ++ xdg_toplevel_set_fullscreen(window->xdg_toplevel, NULL); + else if (action == NET_WM_STATE_REMOVE) +- zxdg_toplevel_v6_unset_fullscreen(window->xdg_toplevel); ++ xdg_toplevel_unset_fullscreen(window->xdg_toplevel); + } + + if (changed[ATOM_NET_WM_STATE_MAXIMIZED_VERT] && +@@ -2411,9 +2407,9 @@ static void sl_handle_client_message(struct sl_context* ctx, + "action", net_wm_state_to_string(action), "window->name", + window->name); + if (action == NET_WM_STATE_ADD) +- zxdg_toplevel_v6_set_maximized(window->xdg_toplevel); ++ xdg_toplevel_set_maximized(window->xdg_toplevel); + else if (action == NET_WM_STATE_REMOVE) +- zxdg_toplevel_v6_unset_maximized(window->xdg_toplevel); ++ xdg_toplevel_unset_maximized(window->xdg_toplevel); + } + } + } else if (event->type == ctx->atoms[ATOM_WM_CHANGE_STATE].value && +@@ -2422,7 +2418,7 @@ static void sl_handle_client_message(struct sl_context* ctx, + TRACE_EVENT("x11wm", "XCB_CLIENT_MESSAGE: WM_STATE_ICONIC (minimize)", + "window->name", window ? window->name : "<unknown>"); + if (window && window->xdg_toplevel) { +- zxdg_toplevel_v6_set_minimized(window->xdg_toplevel); ++ xdg_toplevel_set_minimized(window->xdg_toplevel); + } + } + } +@@ -2435,7 +2431,7 @@ static void sl_handle_focus_in(struct sl_context* ctx, + // window was realized. + struct sl_window* parent = sl_lookup_window(ctx, window->transient_for); + if (parent && parent->xdg_toplevel && window->xdg_toplevel) +- zxdg_toplevel_v6_set_parent(window->xdg_toplevel, parent->xdg_toplevel); ++ xdg_toplevel_set_parent(window->xdg_toplevel, parent->xdg_toplevel); + } + } + +@@ -2744,9 +2740,9 @@ static void sl_handle_property_notify(struct sl_context* ctx, + return; + + if (window->name) { +- zxdg_toplevel_v6_set_title(window->xdg_toplevel, window->name); ++ xdg_toplevel_set_title(window->xdg_toplevel, window->name); + } else { +- zxdg_toplevel_v6_set_title(window->xdg_toplevel, ""); ++ xdg_toplevel_set_title(window->xdg_toplevel, ""); + } + } else if (event->atom == XCB_ATOM_WM_CLASS) { + struct sl_window* window = sl_lookup_window(ctx, event->window); +@@ -2802,19 +2798,19 @@ static void sl_handle_property_notify(struct sl_context* ctx, + return; + + if (window->size_flags & P_MIN_SIZE) { +- zxdg_toplevel_v6_set_min_size(window->xdg_toplevel, +- window->min_width / ctx->scale, +- window->min_height / ctx->scale); ++ xdg_toplevel_set_min_size(window->xdg_toplevel, ++ window->min_width / ctx->scale, ++ window->min_height / ctx->scale); + } else { +- zxdg_toplevel_v6_set_min_size(window->xdg_toplevel, 0, 0); ++ xdg_toplevel_set_min_size(window->xdg_toplevel, 0, 0); + } + + if (window->size_flags & P_MAX_SIZE) { +- zxdg_toplevel_v6_set_max_size(window->xdg_toplevel, +- window->max_width / ctx->scale, +- window->max_height / ctx->scale); ++ xdg_toplevel_set_max_size(window->xdg_toplevel, ++ window->max_width / ctx->scale, ++ window->max_height / ctx->scale); + } else { +- zxdg_toplevel_v6_set_max_size(window->xdg_toplevel, 0, 0); ++ xdg_toplevel_set_max_size(window->xdg_toplevel, 0, 0); + } + } else if (event->atom == XCB_ATOM_WM_HINTS) { + struct sl_window* window = sl_lookup_window(ctx, event->window); +diff --git a/vm_tools/sommelier/sommelier.h b/vm_tools/sommelier/sommelier.h +index 79bcf6a3b3..d3157cd8a9 100644 +--- a/vm_tools/sommelier/sommelier.h ++++ b/vm_tools/sommelier/sommelier.h +@@ -400,7 +400,7 @@ struct sl_xdg_shell { + struct sl_context* ctx; + uint32_t id; + struct sl_global* host_global; +- struct zxdg_shell_v6* internal; ++ struct xdg_wm_base* internal; + }; + + struct sl_aura_shell { +@@ -500,9 +500,9 @@ struct sl_window { + int max_height; + struct sl_config next_config; + struct sl_config pending_config; +- struct zxdg_surface_v6* xdg_surface; +- struct zxdg_toplevel_v6* xdg_toplevel; +- struct zxdg_popup_v6* xdg_popup; ++ struct xdg_surface* xdg_surface; ++ struct xdg_toplevel* xdg_toplevel; ++ struct xdg_popup* xdg_popup; + struct zaura_surface* aura_surface; + struct wl_list link; + }; +-- +2.32.0 + diff --git a/pkgs/os-specific/linux/chromium-os/sommelier/default.nix b/pkgs/os-specific/linux/chromium-os/sommelier/default.nix new file mode 100644 index 00000000000..b45ab330c34 --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/sommelier/default.nix @@ -0,0 +1,37 @@ +{ common-mk, lib +, abseil-cpp, mesa, grpc, openssl, libdrm, xlibs, protobuf, wayland +, libxkbcommon, vm_protos, linuxHeaders, c-ares, zlib +}: + +common-mk { + platformSubdir = "vm_tools/sommelier"; + + platform2Patches = [ + ./0005-sommelier-don-t-leak-source-absolute-paths.patch + ./0006-Revert-Revert-vm_tools-sommelier-Switch-to-the-stabl.patch + ]; + + buildInputs = [ + abseil-cpp mesa grpc openssl libdrm protobuf wayland libxkbcommon vm_protos + linuxHeaders c-ares zlib + ] ++ (with xlibs; [ pixman libxcb libX11 ]); + + gnArgs.use_demos = false; + + NIX_CFLAGS_COMPILE = [ + "-Wno-error=sign-compare" + "-Wno-error=stringop-truncation" + "-Wno-error=class-memaccess" + "-Wno-error=maybe-uninitialized" + ]; + + installPhase = '' + mkdir -p $out/bin + install sommelier $out/bin + ''; + + meta = with lib; { + description = "Nested Wayland compositor with support for X11 forwarding"; + maintainers = with maintainers; [ qyliss ]; + }; +} diff --git a/pkgs/applications/virtualization/crosvm/update.py b/pkgs/os-specific/linux/chromium-os/update.py index 29e68b9f579..5852d4a3069 100755 --- a/pkgs/applications/virtualization/crosvm/update.py +++ b/pkgs/os-specific/linux/chromium-os/update.py @@ -1,19 +1,31 @@ #! /usr/bin/env nix-shell -#! nix-shell -p nix-prefetch-git "python3.withPackages (ps: with ps; [ lxml ])" -#! nix-shell -i python +#! nix-shell -i python -p "python3.withPackages (ps: with ps; [ lxml ])" import base64 import json -import re import subprocess from codecs import iterdecode +from os import scandir from os.path import dirname, splitext from lxml import etree from lxml.etree import HTMLParser +from re import MULTILINE, fullmatch, match, search from urllib.request import urlopen -# ChromiumOS components required to build crosvm. -components = ['chromiumos/platform/crosvm', 'chromiumos/third_party/adhd'] +# ChromiumOS components used in Nixpkgs +component_paths = [ + 'src/aosp/external/minijail', + 'src/platform/crosvm', + 'src/platform/minigbm', + 'src/platform2', + 'src/third_party/adhd', + 'src/third_party/chromiumos-overlay', + 'src/third_party/kernel/v5.4', + 'src/third_party/libqmi', + 'src/third_party/modemmanager-next', + 'src/third_party/modp_b64', + 'src/third_party/rust-vmm/vhost', +] git_root = 'https://chromium.googlesource.com/' manifest_versions = f'{git_root}chromiumos/manifest-versions' @@ -29,6 +41,7 @@ buildspecs_url = f'{manifest_versions}/+/refs/heads/master/full/buildspecs/' # documented. with urlopen('https://cros-updates-serving.appspot.com/') as resp: document = etree.parse(resp, HTMLParser()) + # bgcolor="lightgreen" is set on the most up-to-date version for # each channel, so find a lightgreen cell in the "Stable" column. (platform_version, chrome_version) = document.xpath(""" @@ -38,8 +51,8 @@ with urlopen('https://cros-updates-serving.appspot.com/') as resp: ][@bgcolor="lightgreen"])[1]/text() """) -chrome_major_version = re.match(r'\d+', chrome_version)[0] -chromeos_tip_build = re.match(r'\d+', platform_version)[0] +chrome_major_version = match(r'\d+', chrome_version)[0] +chromeos_tip_build = match(r'\d+', platform_version)[0] # Find the most recent buildspec for the stable Chrome version and # Chromium OS build number. Its branch build and branch branch build @@ -54,38 +67,65 @@ with urlopen(f'{buildspecs_url}{chrome_major_version}/?format=TEXT') as resp: buildspecs.sort(reverse=True) buildspec = splitext(buildspecs[0])[0] -revisions = {} +components = {} # Read the buildspec, and extract the git revisions for each component. with urlopen(f'{buildspecs_url}{chrome_major_version}/{buildspec}.xml?format=TEXT') as resp: xml = base64.decodebytes(resp.read()) root = etree.fromstring(xml) + + default_remote = root.find('default').get('remote') + remotes = {} + for remote in root.findall('remote'): + remotes[remote.get('name')] = remote.get('fetch') + for project in root.findall('project'): - revisions[project.get('name')] = project.get('revision') + name = project.get('name') + path = project.get('path') + remote_name = project.get('remote') or default_remote + remote = remotes[remote_name] + + components[path] = { + 'revision': project.get('revision'), + 'url': f'{remote}/{name}', + } # Initialize the data that will be output from this script. Leave the # rc number in buildspec so nobody else is subject to the same level # of confusion I have been. data = {'version': f'{chrome_major_version}.{buildspec}', 'components': {}} +paths = {} + # Fill in the 'components' dictionary with the output from # nix-prefetch-git, which can be passed straight to fetchGit when # imported by Nix. -for component in components: - argv = ['nix-prefetch-git', - '--url', git_root + component, - '--rev', revisions[component]] - - output = subprocess.check_output(argv) - data['components'][component] = json.loads(output.decode('utf-8')) +for path in component_paths: + name = path.split('/')[-1] + url = components[path]['url'] + rev = components[path]['revision'] + tarball = f'{url}/+archive/{rev}.tar.gz' + output = subprocess.check_output(['nix-prefetch-url', '--print-path', '--unpack', '--name', name, tarball]) + (sha256, store_path) = output.decode('utf-8').splitlines() + paths[path] = store_path + data['components'][path] = { + 'name': name, + 'url': url, + 'rev': rev, + 'sha256': sha256, + } -# Find the path to crosvm's default.nix, so the srcs data can be -# written into the same directory. -argv = ['nix-instantiate', '--eval', '--json', '-A', 'crosvm.meta.position'] -position = json.loads(subprocess.check_output(argv).decode('utf-8')) -filename = re.match(r'[^:]*', position)[0] +# Get the version number of the kernel. +kernel = paths['src/third_party/kernel/v5.4'] +makefile = open(f'{kernel}/Makefile').read() +version = search(r'^VERSION = (.+)$', makefile, MULTILINE)[1] +patchlevel = search(r'^PATCHLEVEL = (.*?)$', makefile, MULTILINE)[1] +sublevel = search(r'^SUBLEVEL = (.*?)$', makefile, MULTILINE)[1] +extra = search(r'^EXTRAVERSION =[ \t]*(.*?)$', makefile, MULTILINE)[1] +full_ver = '.'.join(filter(None, [version, patchlevel, sublevel])) + extra +data['components']['src/third_party/kernel/v5.4']['version'] = full_ver # Finally, write the output. -with open(dirname(filename) + '/upstream-info.json', 'w') as out: +with open(dirname(__file__) + '/upstream-info.json', 'w') as out: json.dump(data, out, indent=2) out.write('\n') diff --git a/pkgs/os-specific/linux/chromium-os/upstream-info.json b/pkgs/os-specific/linux/chromium-os/upstream-info.json new file mode 100644 index 00000000000..f23948d9cb4 --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/upstream-info.json @@ -0,0 +1,72 @@ +{ + "version": "91.13904.0.0-rc2", + "components": { + "src/aosp/external/minijail": { + "name": "minijail", + "url": "https://android.googlesource.com/platform/external/minijail", + "rev": "4f830bddad22ccbb5862a866efd9931393a4b83b", + "sha256": "044ll9jmanjlv6ibb8n77nsqifsb1iqck3bgkyix43i3yqamlq5h" + }, + "src/platform/crosvm": { + "name": "crosvm", + "url": "https://chromium.googlesource.com/chromiumos/platform/crosvm", + "rev": "401340ee7fa81db720a4f7a9476b6eea133e5b64", + "sha256": "0wbfprqqm0hqhypdb0x90bqn65kv0f3vpibr84p3paby6hmx14y2" + }, + "src/platform/minigbm": { + "name": "minigbm", + "url": "https://chromium.googlesource.com/chromiumos/platform/minigbm", + "rev": "231913e75751498902132c825d5b8567684e3b8d", + "sha256": "03wcdwd4l0wg9k6z9nnqim2wqqddlmppa49v6bkry7mhmiar1jc9" + }, + "src/platform2": { + "name": "platform2", + "url": "https://chromium.googlesource.com/chromiumos/platform2", + "rev": "1fcefaa166e868069ad1b81091333ff75e0657f6", + "sha256": "1p4rcq53qz35sfbqldmcnjz5ikjxppdw1xcb348zn8n3hnb6vmqf" + }, + "src/third_party/adhd": { + "name": "adhd", + "url": "https://chromium.googlesource.com/chromiumos/third_party/adhd", + "rev": "3624a4296888926a21462bfd499d4ba91268046b", + "sha256": "0flph3fagyl21dbwpdvhhizwnhbrgll87yfpq1i00xzr0c9xc1cc" + }, + "src/third_party/chromiumos-overlay": { + "name": "chromiumos-overlay", + "url": "https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay", + "rev": "f5b0e4767c2e5f8caa899127c8b3060fda2a3694", + "sha256": "1vpfccb0ikqa1xh6m0wizbxcaick2arki7d76sacz8qgrxinq8mn" + }, + "src/third_party/kernel/v5.4": { + "name": "v5.4", + "url": "https://chromium.googlesource.com/chromiumos/third_party/kernel", + "rev": "15178e41cf17cd7ce9f9a087bcb0677eaa57f82b", + "sha256": "0cwvxm5bx0xs80l2rq3dqj88445qdhiqxp1999ix1gcc8awvwzdb", + "version": "5.4.109" + }, + "src/third_party/libqmi": { + "name": "libqmi", + "url": "https://chromium.googlesource.com/chromiumos/third_party/libqmi", + "rev": "d9def40a2e068fd7e961aa0a4c699cf62cb8672c", + "sha256": "0grf510l85p32hc8gn7ks12ma0c2s3gnk76dyq62kmrvfb43ijzm" + }, + "src/third_party/modemmanager-next": { + "name": "modemmanager-next", + "url": "https://chromium.googlesource.com/chromiumos/third_party/modemmanager-next", + "rev": "2de7877b2662d64c162434a7d3fb89d43f24b913", + "sha256": "027pnj92kidfgrzfpgwz18pl7gjgxi128il6wx1s8jdxsk2m00jc" + }, + "src/third_party/modp_b64": { + "name": "modp_b64", + "url": "https://chromium.googlesource.com/aosp/platform/external/modp_b64", + "rev": "269b6fb8401617b85e2dff7ae8a7b0f97613e2cd", + "sha256": "1mc5w70svgj7rq49r6lxkw9ix6q09dxrw0lamx3hn8anq5q8y532" + }, + "src/third_party/rust-vmm/vhost": { + "name": "vhost", + "url": "https://chromium.googlesource.com/chromiumos/third_party/rust-vmm/vhost", + "rev": "98298cb96972c20e05bffed58861456b48328d43", + "sha256": "0ym5cmnaifn3ywcidvqmbswmsxqi0zw6gx88gfqfq0p5jis8vjhi" + } + } +} diff --git a/pkgs/os-specific/linux/chromium-os/vm_protos/0003-common-mk-add-goproto_library-source_relative-opt.patch b/pkgs/os-specific/linux/chromium-os/vm_protos/0003-common-mk-add-goproto_library-source_relative-opt.patch new file mode 100644 index 00000000000..e921abd8032 --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/vm_protos/0003-common-mk-add-goproto_library-source_relative-opt.patch @@ -0,0 +1,48 @@ +From 211eea8e623c9e9beb61f38720c718f080bae883 Mon Sep 17 00:00:00 2001 +From: Alyssa Ross <hi@alyssa.is> +Date: Mon, 28 Jun 2021 17:10:46 +0000 +Subject: [PATCH 3/6] common-mk: add goproto_library source_relative opt + +We need this for the go_package changes in protoc-gen-go 1.5.x. If we +didn't use source-relative paths, the full module path would be +repeated in the output location, so we'd get paths like +src/chromiumos/vm_tools/vm_crash/chromiumos/vm_tools/vm_crash/vm_crash.pb.go. + +To avoid the duplication, we either need to set source_relative, or +set proto_out_dir to just go/src. The latter isn't workable, because +then everything two libraries that both use common.proto will both +generate outputs called "go/src/common.pb.go", which will upset GN. + +Reviewed-by: Cole Helbling <cole.e.helbling@outlook.com> +--- + common-mk/proto_library.gni | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/common-mk/proto_library.gni b/common-mk/proto_library.gni +index fb9fb4231d..23645a134f 100644 +--- a/common-mk/proto_library.gni ++++ b/common-mk/proto_library.gni +@@ -225,6 +225,9 @@ template("proto_library") { + # proto_lib_dirs (optional) + # Directories to search for protos a proto file depends on. + # proto_in_dir and "${sysroot}/usr/share/proto" are added by default. ++# source_relative (optional) ++# If true, the output file is placed in the same relative directory as the ++# input file (but under proto_out_dir). + template("goproto_library") { + action(target_name) { + forward_variables_from(invoker, +@@ -254,6 +257,10 @@ template("goproto_library") { + + go_plugin_parameters = [] + ++ if (defined(invoker.source_relative) && invoker.source_relative) { ++ go_plugin_parameters += [ "paths=source_relative" ] ++ } ++ + if (defined(invoker.gen_grpc) && invoker.gen_grpc) { + go_plugin_parameters += [ "plugins=grpc" ] + } +-- +2.32.0 + diff --git a/pkgs/os-specific/linux/chromium-os/vm_protos/0004-vm_tools-proto-set-go_package-correctly.patch b/pkgs/os-specific/linux/chromium-os/vm_protos/0004-vm_tools-proto-set-go_package-correctly.patch new file mode 100644 index 00000000000..d77bcf2bdef --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/vm_protos/0004-vm_tools-proto-set-go_package-correctly.patch @@ -0,0 +1,102 @@ +From fae12c5b06864c0a9687320735c9bed9219c30c8 Mon Sep 17 00:00:00 2001 +From: Alyssa Ross <hi@alyssa.is> +Date: Wed, 16 Jun 2021 16:09:01 +0000 +Subject: [PATCH 4/6] vm_tools: proto: set go_package correctly + +protoc-gen-go 1.5.x has become a lot stricter about this. We have to +use import_mapping for common.proto because it ends up being included +in multiple Go libraries. I'm not sure why it needs to be built once +per library, but that's the way it works. + +Reviewed-by: Cole Helbling <cole.e.helbling@outlook.com> +--- + vm_tools/proto/BUILD.gn | 5 +++++ + vm_tools/proto/tremplin.proto | 2 +- + vm_tools/proto/vm_crash.proto | 2 +- + vm_tools/proto/vm_guest.proto | 1 + + vm_tools/proto/vm_host.proto | 1 + + 5 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/vm_tools/proto/BUILD.gn b/vm_tools/proto/BUILD.gn +index 79c9b94c9f..aadc40165c 100644 +--- a/vm_tools/proto/BUILD.gn ++++ b/vm_tools/proto/BUILD.gn +@@ -60,6 +60,8 @@ goproto_library("vm-crash-gorpcs") { + proto_in_dir = "./" + proto_out_dir = "go/src/chromiumos/vm_tools/vm_crash" + gen_grpc = true ++ source_relative = true ++ import_mapping = [ "common.proto=chromiumos/vm_tools/vm_crash" ] + sources = [ + "${proto_in_dir}/common.proto", + "${proto_in_dir}/vm_crash.proto", +@@ -97,6 +99,7 @@ goproto_library("tremplin-gorpcs") { + proto_in_dir = "./" + proto_out_dir = "go/src/chromiumos/vm_tools/tremplin_proto" + gen_grpc = true ++ source_relative = true + sources = [ "${proto_in_dir}/tremplin.proto" ] + } + +@@ -120,6 +123,8 @@ goproto_library("vm-gorpcs") { + proto_in_dir = "./" + proto_out_dir = "go/src/chromiumos/vm_tools/vm_rpc" + gen_grpc = true ++ source_relative = true ++ import_mapping = [ "common.proto=chromiumos/vm_tools/vm_rpc" ] + sources = [ + "${proto_in_dir}/common.proto", + "${proto_in_dir}/vm_guest.proto", +diff --git a/vm_tools/proto/tremplin.proto b/vm_tools/proto/tremplin.proto +index aac76f7a9e..e6a7bbed0e 100644 +--- a/vm_tools/proto/tremplin.proto ++++ b/vm_tools/proto/tremplin.proto +@@ -8,7 +8,7 @@ option cc_enable_arenas = true; + + // This file defines services for tremplin, the container springboard service. + package vm_tools.tremplin; +-option go_package = "tremplin_proto"; ++option go_package = "chromiumos/vm_tools/tremplin_proto"; + + // This needs to be duplicated because the gyp rule for building + // go code makes it difficult to have imports. +diff --git a/vm_tools/proto/vm_crash.proto b/vm_tools/proto/vm_crash.proto +index 6e4f62fe13..3cd4279989 100644 +--- a/vm_tools/proto/vm_crash.proto ++++ b/vm_tools/proto/vm_crash.proto +@@ -7,7 +7,7 @@ syntax = "proto3"; + option cc_enable_arenas = true; + + package vm_tools.cicerone; +-option go_package = "vm_crash"; ++option go_package = "chromiumos/vm_tools/vm_crash"; + + import "common.proto"; + +diff --git a/vm_tools/proto/vm_guest.proto b/vm_tools/proto/vm_guest.proto +index 86f11d0812..d0946078d5 100644 +--- a/vm_tools/proto/vm_guest.proto ++++ b/vm_tools/proto/vm_guest.proto +@@ -8,6 +8,7 @@ option cc_enable_arenas = true; + + // This file defines services that will be running in the guest VM. + package vm_tools; ++option go_package = "chromiumos/vm_tools/vm_rpc"; + + import "common.proto"; + import "google/protobuf/timestamp.proto"; +diff --git a/vm_tools/proto/vm_host.proto b/vm_tools/proto/vm_host.proto +index a8bd066f61..19759b0271 100644 +--- a/vm_tools/proto/vm_host.proto ++++ b/vm_tools/proto/vm_host.proto +@@ -8,6 +8,7 @@ option cc_enable_arenas = true; + + // This file defines services that will be running on the host for the VM. + package vm_tools; ++option go_package = "chromiumos/vm_tools/vm_rpc"; + + import "common.proto"; + +-- +2.32.0 + diff --git a/pkgs/os-specific/linux/chromium-os/vm_protos/default.nix b/pkgs/os-specific/linux/chromium-os/vm_protos/default.nix new file mode 100644 index 00000000000..cded9c988b3 --- /dev/null +++ b/pkgs/os-specific/linux/chromium-os/vm_protos/default.nix @@ -0,0 +1,41 @@ +{ common-mk, lib, go-protobuf, grpc, openssl, protobuf }: + +common-mk { + pname = "vm_protos"; + platformSubdir = "vm_tools/proto"; + + nativeBuildInputs = [ go-protobuf ]; + buildInputs = [ grpc openssl protobuf ]; + + platform2Patches = [ + ./0003-common-mk-add-goproto_library-source_relative-opt.patch + ./0004-vm_tools-proto-set-go_package-correctly.patch + ]; + + NIX_CFLAGS_COMPILE = [ + "-Wno-error=array-bounds" + "-Wno-error=deprecated-declarations" + ]; + + postPatch = '' + substituteInPlace common-mk/proto_library.gni \ + --replace /usr/bin/grpc_cpp_plugin ${grpc}/bin/grpc_cpp_plugin + ''; + + installPhase = '' + mkdir -p $out/lib/pkgconfig + install -m 644 ../../vm_tools/proto/vm_protos.pc $out/lib/pkgconfig + + headerPath=include/vm_protos/proto_bindings + mkdir -p $out/$headerPath + install -m 644 gen/$headerPath/*.h $out/$headerPath + + install -m 644 *.a $out/lib + ''; + + meta = with lib; { + description = "Protobuf definitions for Chromium OS system VMs"; + maintainers = with maintainers; [ qyliss ]; + platform = platforms.all; + }; +} diff --git a/pkgs/os-specific/linux/kernel-headers/default.nix b/pkgs/os-specific/linux/kernel-headers/default.nix index 9d727838b3f..8b7b5a4fa42 100644 --- a/pkgs/os-specific/linux/kernel-headers/default.nix +++ b/pkgs/os-specific/linux/kernel-headers/default.nix @@ -5,7 +5,7 @@ assert stdenvNoCC.hostPlatform.isAndroid -> (flex != null && bison != null && python != null && rsync != null); -let +rec { makeLinuxHeaders = { src, version, patches ? [] }: stdenvNoCC.mkDerivation { inherit src; @@ -78,8 +78,10 @@ let platforms = platforms.linux; }; }; -in { - inherit makeLinuxHeaders; + + linuxHeadersPatches = [ + ./no-relocs.patch # for building x86 kernel headers on non-ELF platforms + ]; linuxHeaders = let version = "5.12"; in makeLinuxHeaders { @@ -88,8 +90,6 @@ in { url = "mirror://kernel/linux/kernel/v5.x/linux-${version}.tar.xz"; sha256 = "sha256-fQ328r8jhNaNC9jh/j4HHWQ2Tc3GAC57XIfJLUj6w2Y="; }; - patches = [ - ./no-relocs.patch # for building x86 kernel headers on non-ELF platforms - ]; + patches = linuxHeadersPatches; }; } diff --git a/pkgs/os-specific/linux/kernel/linux-cros.nix b/pkgs/os-specific/linux/kernel/linux-cros.nix new file mode 100644 index 00000000000..edaa33ac0fb --- /dev/null +++ b/pkgs/os-specific/linux/kernel/linux-cros.nix @@ -0,0 +1,38 @@ +{ stdenv, lib, buildPackages, fetchFromGitiles, upstreamInfo, perl, buildLinux +, modDirVersionArg ? null +, ... } @ args: + +let + versionData = upstreamInfo.components."src/third_party/kernel/v5.4"; +in + +with lib; +with lib.kernel; + +buildLinux (args // rec { + inherit (versionData) version; + + # modDirVersion needs to be x.y.z, will automatically add .0 if needed + modDirVersion = + if modDirVersionArg == null + then concatStringsSep "." (take 3 (splitVersion "${version}.0")) + else modDirVersionArg; + + # branchVersion needs to be x.y + extraMeta.branch = versions.majorMinor version; + + src = fetchFromGitiles { inherit (versionData) name url rev sha256; }; + + updateScript = ../chromium-os/update.py; + + structuredExtraConfig = { + # Enabling this (the default) caused a build failure. If you can + # archieve a successful build with this enabled, go ahead and + # enable it. + VIDEO_INTEL_IPU6 = no; + + # RTW88_8822*E were being selected as Y when N/m/? are the only valid options + RTW88_8822BE = lib.mkForce module; + RTW88_8822CE = lib.mkForce module; + } // (args.structuredExtraConfig or {}); +} // (args.argsOverride or {})) diff --git a/pkgs/os-specific/linux/spectrum/default.nix b/pkgs/os-specific/linux/spectrum/default.nix new file mode 100644 index 00000000000..c4cccab3787 --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/default.nix @@ -0,0 +1,18 @@ +{ newScope, linux_cros }: + +let + self = with self; { + callPackage = newScope self; + + sys-vms = callPackage ./vm { }; + + spectrum-vm = callPackage ./spectrum-vm { linux = linux_vm; }; + + spectrum-testhost = callPackage ./testhost { }; + + linux_vm = callPackage ./linux/vm.nix { linux = linux_cros; }; + + makeRootfs = callPackage ./rootfs { }; + }; +in +self diff --git a/pkgs/os-specific/linux/spectrum/linux/vm.nix b/pkgs/os-specific/linux/spectrum/linux/vm.nix new file mode 100644 index 00000000000..c657cb443e8 --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/linux/vm.nix @@ -0,0 +1,25 @@ +{ lib, linux, kernelPatches, structuredExtraConfig ? {} }: + +with lib.kernel; + +linux.override { + structuredExtraConfig = { + VIRTIO_PCI = yes; + VIRTIO_BLK = yes; + VIRTIO_WL = yes; + VIRTIO_NET = yes; + DEVTMPFS_MOUNT = yes; + SQUASHFS = yes; + + # VOP is needed to work around a Kconfig bug: + # https://lore.kernel.org/lkml/87wob4tf9b.fsf@alyssa.is/ + VOP = yes; + VOP_BUS = yes; + HW_RANDOM = yes; + HW_RANDOM_VIRTIO = yes; + + NET_9P = yes; + NET_9P_VIRTIO = yes; + "9P_FS" = yes; + } // structuredExtraConfig; +} diff --git a/pkgs/os-specific/linux/spectrum/rootfs/default.nix b/pkgs/os-specific/linux/spectrum/rootfs/default.nix new file mode 100644 index 00000000000..56f2d15b103 --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/rootfs/default.nix @@ -0,0 +1,58 @@ +{ runCommandNoCC, writeScript, writeReferencesToFile, makeFontsConf, lib +, dash, execline, s6, s6-rc, s6-portable-utils, s6-linux-utils, s6-linux-init, busybox +, mesa, squashfs-tools-ng, makeDBusConf, connman +}: + +{ services, rcServices ? {}, fonts ? [], path ? [] }: + +let + stage1 = import ./stage1.nix { + inherit writeScript lib + execline s6 s6-rc s6-portable-utils s6-linux-utils s6-linux-init busybox mesa + path; + }; + + makeServicesDir = import ./services.nix { + inherit runCommandNoCC writeScript lib execline; + }; + + makeRcServicesDir = import ./rc-services.nix { + inherit runCommandNoCC lib s6-rc; + }; + + fontsConf = makeFontsConf { fontDirectories = fonts; }; + + squashfs = runCommandNoCC "root-squashfs" {} '' + cd ${rootfs} + ( + grep -v ^${rootfs} ${writeReferencesToFile rootfs} + printf "%s\n" * + ) \ + | xargs tar -cP --owner root:0 --group root:0 --hard-dereference \ + | ${squashfs-tools-ng}/bin/tar2sqfs -c gzip -X level=1 $out + ''; + + rootfs = runCommandNoCC "rootfs" { passthru = { inherit squashfs; }; } '' + mkdir $out + cd $out + + mkdir -p bin sbin dev proc run sys tmp var/lib + ln -s /run var/run + ln -s ${dash}/bin/dash bin/sh + ln -s ${stage1} sbin/init + cp -r ${./etc} etc + chmod u+w etc + ln -s ${makeDBusConf { + suidHelper = "/run/dbus-daemon-launch-helper"; + serviceDirectories = [ connman ]; + }} etc/dbus-1 + + mkdir etc/fonts + ln -s ${fontsConf} etc/fonts/fonts.conf + + touch etc/login.defs + cp -r ${makeServicesDir { inherit services; }} etc/service + cp -r ${makeRcServicesDir { services = rcServices; }} etc/s6-rc + ''; +in +rootfs diff --git a/pkgs/os-specific/linux/spectrum/rootfs/etc/group b/pkgs/os-specific/linux/spectrum/rootfs/etc/group new file mode 100644 index 00000000000..df4940a5516 --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/rootfs/etc/group @@ -0,0 +1,3 @@ +root:x:0:root +messagebus:x:4:messagebus +user:x:1000:user diff --git a/pkgs/os-specific/linux/spectrum/rootfs/etc/passwd b/pkgs/os-specific/linux/spectrum/rootfs/etc/passwd new file mode 100644 index 00000000000..ddb1f854a6e --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/rootfs/etc/passwd @@ -0,0 +1,3 @@ +root:x:0:0:System administrator:/:/bin/sh +messagebus:x:4:4:D-Bus system message bus daemon user:/run/dbus:/bin/sh +user:x:1000:1000:User:/:/bin/sh diff --git a/pkgs/os-specific/linux/spectrum/rootfs/etc/wayfire/wf-shell-defaults.ini b/pkgs/os-specific/linux/spectrum/rootfs/etc/wayfire/wf-shell-defaults.ini new file mode 100644 index 00000000000..7ba621225aa --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/rootfs/etc/wayfire/wf-shell-defaults.ini @@ -0,0 +1,2 @@ +[panel] +widgets_right = diff --git a/pkgs/os-specific/linux/spectrum/rootfs/rc-services.nix b/pkgs/os-specific/linux/spectrum/rootfs/rc-services.nix new file mode 100644 index 00000000000..4c942189c5e --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/rootfs/rc-services.nix @@ -0,0 +1,26 @@ +{ runCommandNoCC, lib, s6-rc }: + +{ services ? [] }: + +let + inherit (lib) concatStrings escapeShellArg mapAttrsToList optionalString; + + source = runCommandNoCC "s6-services-source" {} '' + mkdir $out + ${concatStrings (mapAttrsToList (name: attrs: '' + mkdir $out/${name} + ${concatStrings (mapAttrsToList (key: value: '' + cp ${value} $out/${name}/${key} + '') attrs)} + '') services)} + ''; + + s6RcCompile = { fdhuser ? null }: source: + runCommandNoCC "s6-rc-compile" {} '' + ${s6-rc}/bin/s6-rc-compile \ + ${optionalString (fdhuser != null) "-h ${escapeShellArg fdhuser}"} \ + $out ${source} + ''; +in + +s6RcCompile {} source diff --git a/pkgs/os-specific/linux/spectrum/rootfs/services.nix b/pkgs/os-specific/linux/spectrum/rootfs/services.nix new file mode 100644 index 00000000000..b2b09faa06e --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/rootfs/services.nix @@ -0,0 +1,28 @@ +{ runCommandNoCC, writeScript, lib, execline }: + +{ services ? [] }: + +let + services' = { + ".s6-svscan" = { + finish = writeScript "init-stage3" '' + #! ${execline}/bin/execlineb -P + foreground { s6-nuke -th } + s6-sleep -m -- 2000 + foreground { s6-nuke -k } + wait { } + s6-linux-init-hpr -fr + ''; + } // services.".s6-svscan" or {}; + } // services; +in + +runCommandNoCC "services" {} '' + mkdir $out + ${lib.concatStrings (lib.mapAttrsToList (name: attrs: '' + mkdir $out/${name} + ${lib.concatStrings (lib.mapAttrsToList (key: value: '' + cp ${value} $out/${name}/${key} + '') attrs)} + '') services')} +'' diff --git a/pkgs/os-specific/linux/spectrum/rootfs/stage1.nix b/pkgs/os-specific/linux/spectrum/rootfs/stage1.nix new file mode 100644 index 00000000000..de10d60ffb6 --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/rootfs/stage1.nix @@ -0,0 +1,44 @@ +{ writeScript, lib +, execline, s6, s6-rc, s6-portable-utils, s6-linux-utils, s6-linux-init, busybox, mesa +, path ? [] +}: + +let + path' = path ++ [ + s6 s6-rc s6-portable-utils s6-linux-utils s6-linux-init busybox execline + ]; +in + +writeScript "init-stage1" '' + #! ${execline}/bin/execlineb -P + export PATH ${lib.makeBinPath path'} + ${s6}/bin/s6-setsid -qb -- + + umask 022 + if { s6-mount -t tmpfs -o mode=0755 tmpfs /run } + if { s6-hiercopy /etc/service /run/service } + emptyenv -p + + background { + s6-setsid -- + + if { s6-rc-init -c /etc/s6-rc /run/service } + + if { s6-mkdir -p /run/user/0 /dev/pts /dev/shm } + if { install -o user -g user -d /run/user/1000 } + + if { s6-mount -t devpts -o gid=4,mode=620 none /dev/pts } + if { s6-mount -t tmpfs none /dev/shm } + if { s6-mount -t tmpfs none /var/lib } + if { s6-mount -t proc none /proc } + if { s6-mount -t sysfs none /sys } + + if { s6-ln -s ${mesa.drivers} /run/opengl-driver } + + s6-rc change ok-all + } + + unexport ! + cd /run/service + s6-svscan +'' diff --git a/pkgs/os-specific/linux/spectrum/spectrum-vm/default.nix b/pkgs/os-specific/linux/spectrum/spectrum-vm/default.nix new file mode 100644 index 00000000000..c56d2537c63 --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/spectrum-vm/default.nix @@ -0,0 +1,35 @@ +{ stdenv, lib, makeWrapper, utillinux, crosvm, linux, sys-vms }: + +stdenv.mkDerivation { + name = "spectrum-vm"; + + src = ./spectrum-vm.in; + + nativeBuildInputs = [ makeWrapper ]; + + unpackPhase = '' + cp $src spectrum-vm.in + ''; + + configurePhase = '' + substituteAll spectrum-vm.in spectrum-vm + chmod +x spectrum-vm + ''; + + getopt = "${lib.getBin utillinux}/bin/getopt"; + crosvm = "${lib.getBin crosvm}/bin/crosvm"; + kernel = "${sys-vms.comp.linux}/bzImage"; + rootfs = sys-vms.comp.rootfs.squashfs; + + installPhase = '' + mkdir -p $out/bin + cp spectrum-vm $out/bin + ''; + + meta = with lib; { + description = "Utility for testing Spectrum VM components"; + maintainers = with maintainers; [ qyliss ]; + license = licenses.gpl3Plus; + inherit (crosvm.meta) platforms; + }; +} diff --git a/pkgs/os-specific/linux/spectrum/spectrum-vm/spectrum-vm.in b/pkgs/os-specific/linux/spectrum/spectrum-vm/spectrum-vm.in new file mode 100755 index 00000000000..a72c3896141 --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/spectrum-vm/spectrum-vm.in @@ -0,0 +1,71 @@ +#!@shell@ +set -ue + +ex_usage() { + cat <<EOF +Usage: $(basename "$0") [OPTION]... [-- CROSVM_OPTIONS] + + -c COMMAND shell command to run inside VM + -C, --crosvm PATH path to custom crosvm executable + -k, --kernel PATH path to custom kernel image + -f, --rootfs PATH path to custom root file system image + -- CROSVM_OPTIONS extra arguments to pass to crosvm +EOF + exit "$1" +} + +args="$(@getopt@ -s sh -l crosvm:,help,kernel:,rootfs: -o c:C:hk:f: -- "$@" || exit 1)" +eval set -- "$args" + +command= +crosvm=@crosvm@ +kernel=@kernel@ +rootfs=@rootfs@ + +while : +do + case "$1" in + -c) + shift + command="$1" + shift + ;; + -C|--crosvm) + shift + crosvm="$1" + shift + ;; + -h|--help) + ex_usage 0 + ;; + -k|--kernel) + shift + kernel="$1" + shift + ;; + -f|--rootfs) + shift + rootfs="$1" + shift + ;; + --) + shift + break + ;; + esac +done + +if [ -n "${XDG_RUNTIME_DIR-}" ] +then + set -- -s "$XDG_RUNTIME_DIR" "$@" + if [ -n "${WAYLAND_DISPLAY-}" ] + then set -- --wayland-sock "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" "$@" + fi +fi + +exec "$crosvm" run \ + -p init=/sbin/init \ + -p "spectrumcmd=$(printf %s "$command" | base64 -w0)" \ + --root "$rootfs" \ + "$@" \ + "$kernel" diff --git a/pkgs/os-specific/linux/spectrum/testhost/default.nix b/pkgs/os-specific/linux/spectrum/testhost/default.nix new file mode 100644 index 00000000000..de62f0add67 --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/testhost/default.nix @@ -0,0 +1,218 @@ +{ lib, runCommandNoCC, writeScript, writeScriptBin, writeShellScript, writeText +, coreutils, cloud-hypervisor, crosvm, curl, execline, gnutar, gnused, iproute +, iptables, jq, kmod, mktuntap, rsync, s6, s6-rc, sys-vms, utillinux +}: + +let + inherit (lib) concatStrings escapeShellArg makeBinPath mapAttrsToList + optionalString; + + compose2 = f: g: a: b: f (g a b); + + concatMapAttrs = compose2 concatStrings mapAttrsToList; + + makeServicesDir = { services }: + runCommandNoCC "services" {} '' + mkdir $out + ${concatMapAttrs (name: attrs: '' + mkdir $out/${name} + ${concatMapAttrs (key: value: '' + cp -r ${value} $out/${name}/${key} + '') attrs} + '') services} + ''; + + s6RcCompile = { fdhuser ? null }: source: + runCommandNoCC "s6-rc-compile" {} '' + ${s6-rc}/bin/s6-rc-compile \ + ${optionalString (fdhuser != null) "-h ${escapeShellArg fdhuser}"} \ + dest ${source} + tar -C dest -cf $out . + ''; + + compiledRcServicesDir = s6RcCompile {} (makeServicesDir { + services = { + vm-app = { + run = writeScript "app-run" '' + #! ${execline}/bin/execlineb -S0 + # fdclose 0 + + # Checking the return value of the bridge creation is + # important, because if it fails due to the bridge already + # existing that means something else could already be using + # this bridge. + if { ip link add name br0 type bridge } + if { ip link set br0 up } + + # Calculate the MACs for our TAP and the router's TAP. + # MAC address format, by octet: + # + # 0-3 Static OUI for Spectrum + # 4 Most significant bit is used to differentiate + # routers from clients. Other bits are reserved. + # 5-6 Last two octets of client's IP (in 100.64.0.0/16). + # + backtick -i router_mac { + pipeline { printf %.4x ${toString sys-vms.app.vmID} } + sed s/^\\(..\\)\\(..\\)$/0A:B3:EC:80:\\1:\\2/ + } + backtick -i client_mac { + pipeline { printf %.4x ${toString sys-vms.app.vmID} } + sed s/^\\(..\\)\\(..\\)$/0A:B3:EC:00:\\1:\\2/ + } + multisubstitute { + importas -iu router_mac router_mac + importas -iu client_mac client_mac + } + + # Create the net VM end, and attach it to the net VM. + # + # Use a hardcoded name for now because if we use a dynamic + # one iproute2 has no way of telling us the name that was + # chosen: + # https://lore.kernel.org/netdev/20210406134240.wwumpnrzfjbttnmd@eve.qyliss.net/ + define other_tap_name vmtapnet + # Try to delete the device in case the VM was powered off + # (as the finish script wouldn't have been run in that + # case.) Since we check the return value of ip tuntap add, + # in the case of a race condition between deleting the + # device and creating it again, we'll just fail and try + # again. + foreground { ip link delete $other_tap_name } + if { ip tuntap add name $other_tap_name mode tap } + if { ip link set $other_tap_name master br0 } + if { ip link set $other_tap_name up } + if { + pipeline { + jq -n "$ARGS.named" + --arg tap $other_tap_name + --arg mac $router_mac + } + curl -iX PUT + -H "Accept: application/json" + -H "Content-Type: application/json" + --data-binary @- + --unix-socket ../vm-net/env/cloud-hypervisor.sock + http://localhost/api/v1/vm.add-net + } + + mktuntap -pvBi vmtap%d 6 + importas -iu tap_name TUNTAP_NAME + if { ip link set $tap_name master br0 } + if { ip link set $tap_name up } + if { iptables -t nat -A POSTROUTING -o $tap_name -j MASQUERADE } + + ${crosvm}/bin/crosvm run -p init=/sbin/init -p notifyport=''${port} + # --serial type=file,path=/tmp/app.log + --cid 4 + --tap-fd 6,mac=''${client_mac} + --root ${sys-vms.app.rootfs.squashfs} ${sys-vms.app.linux}/bzImage + ''; + finish = writeScript "app-finish" '' + #! ${execline}/bin/execlineb -S0 + # TODO: remove from vm-net + foreground { ip link delete vmtapnet } + ip link delete br0 + ''; + type = writeText "app-type" '' + longrun + ''; + dependencies = writeText "app-dependencies" '' + vm-net + ''; + }; + + vm-net = { + run = writeScript "net-run" '' + #! ${execline}/bin/execlineb -S0 + # This is only necessary for when running s6 from a tty. + # (i.e. when debugging or running the demo). + redirfd -w 0 /dev/null + + define PCI_LOCATION 0000:00:19.0 + define PCI_PATH /sys/bus/pci/devices/''${PCI_LOCATION} + + # Unbind the network device from the driver it's already + # attached to, if any. + foreground { + redirfd -w 1 ''${PCI_PATH}/driver/unbind + printf "%s" $PCI_LOCATION + } + + # Tell the VFIO driver it should support our device. This + # is allowed to fail because it might already know that, in + # which case it'll return EEXIST. + if { modprobe vfio-pci } + backtick -in device_id { + if { dd bs=2 skip=1 count=2 status=none if=''${PCI_PATH}/vendor } + if { printf " " } + dd bs=2 skip=1 count=2 status=none if=''${PCI_PATH}/device + } + importas -iu device_id device_id + foreground { + redirfd -w 1 /sys/bus/pci/drivers/vfio-pci/new_id + printf "%s" $device_id + } + + # Bind the device to the VFIO driver. This is allowed to + # fail because the new_id operation we just tried will have + # bound it automatically for us if it succeeded. In such a + # case, the kernel will return ENODEV (conistency!). + foreground { + redirfd -w 1 /sys/bus/pci/drivers/vfio-pci/bind + printf "%s" $PCI_LOCATION + } + + # Because we allow both new_id and bind to fail, we need to + # manually make sure now that at least one of them succeeded + # and the device is actually attached to the vfio-driver. + if { test -e /sys/bus/pci/drivers/vfio-pci/''${PCI_LOCATION} } + + foreground { mkdir env } + + ${cloud-hypervisor}/bin/cloud-hypervisor + --api-socket env/cloud-hypervisor.sock + --console off + # --serial tty + --cmdline "console=ttyS0 panic=30 root=/dev/vda" + --device path=''${PCI_PATH} + --disk path=${sys-vms.net.rootfs.squashfs},readonly=on + --kernel ${sys-vms.net.linux.dev}/vmlinux + ''; + type = writeText "net-type" '' + longrun + ''; + }; + }; + }); + + servicesDir = makeServicesDir { + services = { + ".s6-svscan" = { + finish = writeShellScript ".s6-svscan-finish" ""; + }; + }; + }; +in + +writeScriptBin "spectrum-testhost" '' + #! ${execline}/bin/execlineb -S0 + export PATH ${makeBinPath [ + coreutils curl execline gnused gnutar iproute iptables jq kmod mktuntap rsync + s6 s6-rc + ]} + + if { redirfd -w 1 /proc/sys/net/ipv4/ip_forward echo 1 } + + importas -iu runtime_dir XDG_RUNTIME_DIR + backtick -in TOP { mktemp -dp $runtime_dir spectrum.XXXXXXXXXX } + importas -iu top TOP + if { echo $top } + if { rsync -r --chmod=Du+w ${servicesDir}/ ''${top}/service } + background { + if { mkdir -p ''${top}/s6-rc/compiled } + if { tar -C ''${top}/s6-rc/compiled -xf ${compiledRcServicesDir} } + s6-rc-init -c ''${top}/s6-rc/compiled -l ''${top}/s6-rc/live ''${top}/service + } + s6-svscan ''${top}/service +'' diff --git a/pkgs/os-specific/linux/spectrum/vm/app/default.nix b/pkgs/os-specific/linux/spectrum/vm/app/default.nix new file mode 100644 index 00000000000..f8ff480932c --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/vm/app/default.nix @@ -0,0 +1,58 @@ +{ runCommand, writeScript, writeText, makeRootfs +, busybox, execline, linux_vm, jq, iproute +}: + +runCommand "vm-app" rec { + linux = linux_vm; + + login = writeScript "login" '' + #! ${execline}/bin/execlineb -s0 + unexport ! + ${busybox}/bin/login -p -f root $@ + ''; + + rootfs = makeRootfs { + rcServices.ok-all = { + type = writeText "ok-all-type" '' + bundle + ''; + contents = writeText "ok-all-contents" '' + net + ''; + }; + + rcServices.net = { + type = writeText "net-type" '' + oneshot + ''; + up = writeText "net-up" '' + backtick -i LOCAL_IP { + pipeline { ip -j link show eth0 } + pipeline { jq -r ".[0].address | split(\":\") | .[4:6] | \"0x\" + .[]" } + xargs printf "100.64.%d.%d" + } + importas -iu LOCAL_IP LOCAL_IP + + if { ip address add ''${LOCAL_IP}/32 dev eth0 } + if { ip link set eth0 up } + if { ip route add 169.254.0.1 dev eth0 } + ip route add default via 169.254.0.1 dev eth0 + ''; + }; + + services.getty.run = writeScript "getty-run" '' + #! ${execline}/bin/execlineb -P + ${busybox}/bin/getty -i -n -l ${login} 38400 ttyS0 + ''; + + path = [ iproute jq ]; + }; + + inherit (rootfs) squashfs; + vmID = 0; +} '' + mkdir $out + echo "$vmID" > $out/vm-id + ln -s $linux/bzImage $out/kernel + ln -s $squashfs $out/squashfs +'' diff --git a/pkgs/os-specific/linux/spectrum/vm/comp/default.nix b/pkgs/os-specific/linux/spectrum/vm/comp/default.nix new file mode 100644 index 00000000000..eb6317ed6f2 --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/vm/comp/default.nix @@ -0,0 +1,73 @@ +{ lib, makeRootfs, runCommand, writeScript, writeText +, busybox, emacs-nox, execline, gcc, linux_vm, s6, sommelier, source-code-pro +, tinywl, westonLite, zsh +}: + +runCommand "vm-comp" rec { + linux = linux_vm; + + path = [ + busybox emacs-nox execline gcc s6 sommelier tinywl westonLite zsh + ]; + + login = writeScript "login" '' + #! ${execline}/bin/execlineb -s0 + unexport ! + ${busybox}/bin/login -p -f root $@ + ''; + + rootfs = makeRootfs { + services.getty.run = writeScript "getty-run" '' + #! ${execline}/bin/execlineb -P + ${busybox}/bin/getty -i -n -l ${login} 38400 ttyS0 + ''; + + rcServices.ok-all = { + type = writeText "ok-all-type" '' + bundle + ''; + contents = writeText "ok-all-contents" '' + compositor + ''; + }; + + rcServices.compositor = { + type = writeText "compositor-type" '' + longrun + ''; + run = writeScript "compositor-run" '' + #! ${execline}/bin/execlineb -S0 + + s6-applyuidgid -u 1000 -g 1000 + + export HOME / + export PATH ${lib.makeBinPath path} + export XDG_RUNTIME_DIR /run/user/1000 + export XKB_DEFAULT_LAYOUT dvorak + + ${sommelier}/bin/sommelier + ${tinywl}/bin/tinywl -s "weston-terminal --shell $(command -v zsh)" + ''; + dependencies = writeText "compositor-dependencies" '' + wl0 + ''; + }; + + rcServices.wl0 = { + type = writeText "wl0-type" '' + oneshot + ''; + up = writeText "wl0-run" '' + chown user /dev/wl0 + ''; + }; + + fonts = [ source-code-pro ]; + }; + + inherit (rootfs) squashfs; +} '' + mkdir $out + ln -s $linux/bzImage $out/kernel + ln -s $squashfs $out/squashfs +'' diff --git a/pkgs/os-specific/linux/spectrum/vm/default.nix b/pkgs/os-specific/linux/spectrum/vm/default.nix new file mode 100644 index 00000000000..f5d591a960a --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/vm/default.nix @@ -0,0 +1,9 @@ +{ callPackage }: + +{ + app = callPackage ./app { }; + + comp = callPackage ./comp { }; + + net = callPackage ./net { }; +} diff --git a/pkgs/os-specific/linux/spectrum/vm/net/default.nix b/pkgs/os-specific/linux/spectrum/vm/net/default.nix new file mode 100644 index 00000000000..5921b62fcf7 --- /dev/null +++ b/pkgs/os-specific/linux/spectrum/vm/net/default.nix @@ -0,0 +1,167 @@ +{ lib, makeRootfs, runCommand, writeScript, writeText +, busybox, connman, dbus, execline, iptables, iproute, jq, linux_vm, mdevd +}: + +runCommand "vm-net" rec { + linux = linux_vm.override { + structuredExtraConfig = with lib.kernel; { + E1000E = yes; + IGB = yes; + PACKET = yes; + + IP_NF_NAT = yes; + IP_NF_IPTABLES = yes; + IP_NF_TARGET_MASQUERADE = yes; + NF_CONNTRACK = yes; + }; + }; + + login = writeScript "login" '' + #! ${execline}/bin/execlineb -s0 + unexport ! + ${busybox}/bin/login -p -f root $@ + ''; + + rootfs = makeRootfs { + rcServices.ok-all = { + type = writeText "ok-all-type" '' + bundle + ''; + contents = writeText "ok-all-contents" '' + mdevd-coldplug + ''; + }; + + rcServices.mdevd = { + type = writeText "mdevd-type" '' + longrun + ''; + run = writeScript "mdevd-run" '' + #! ${execline}/bin/execlineb -P + ${mdevd}/bin/mdevd -D3 -f ${writeText "mdevd.conf" '' + $INTERFACE=.* 0:0 660 ! @${writeScript "interface" '' + #! ${execline}/bin/execlineb -S0 + + multisubstitute { + importas -i DEVPATH DEVPATH + importas -i INTERFACE INTERFACE + } + + ifte + + { + # This interface is connected to another VM. + + # Our IP is encoded in the NIC-specific portion of the + # interface's MAC address. + backtick -i CLIENT_IP { + pipeline { ip -j link show $INTERFACE } + pipeline { jq -r ".[0].address | split(\":\") | .[4:6] | \"0x\" + .[]" } + xargs printf "100.64.%d.%d" + } + importas -iu CLIENT_IP CLIENT_IP + + if { ip address add 169.254.0.1/32 dev $INTERFACE } + if { ip link set $INTERFACE up } + ip route add $CLIENT_IP dev $INTERFACE + } + + { + if { test $INTERFACE != lo } + # This is a physical connection to a network device. + if { iptables -t nat -A POSTROUTING -o $INTERFACE -j MASQUERADE } + s6-rc -u change connman + } + + grep -iq ^0A:B3:EC: /sys/class/net/''${INTERFACE}/address + ''} + ''} + ''; + notification-fd = writeText "mdevd-notification-fd" '' + 3 + ''; + dependencies = writeText "mdevd-dependencies" '' + sysctl + ''; + }; + + rcServices.mdevd-coldplug = { + type = writeText "mdevd-coldplug-type" '' + oneshot + ''; + up = writeText "mdevd-run" '' + ${mdevd}/bin/mdevd-coldplug + ''; + dependencies = writeText "mdevd-coldplug-dependencies" '' + mdevd + ''; + }; + + rcServices.dbus = { + type = writeText "dbus-daemon" '' + longrun + ''; + run = writeScript "dbus-daemon-run" '' + #! ${execline}/bin/execlineb -S0 + foreground { mkdir /run/dbus } + # Busybox cp doesn't have -n to avoid copying to paths that + # already exist, but we can abuse -u for the same effect, + # since every file in the store is from Jan 1 1970. + foreground { cp -u ${dbus}/libexec/dbus-daemon-launch-helper /run } + foreground { chgrp messagebus /run/dbus-daemon-launch-helper } + foreground { chmod 4550 /run/dbus-daemon-launch-helper } + ${dbus}/bin/dbus-daemon + --nofork --nosyslog --nopidfile --config-file=/etc/dbus-1/system.conf + ''; + }; + + rcServices.connman = { + type = writeText "connman-type" '' + longrun + ''; + run = writeScript "connman-run" '' + #! ${execline}/bin/execlineb -S0 + backtick -in HARDWARE_INTERFACES { + pipeline { + find -L /sys/class/net -mindepth 2 -maxdepth 2 -name address -print0 + } + + # Filter out other VMs and the loopback device. + pipeline { xargs -0 grep -iL ^\\(0A:B3:EC:\\|00:00:00:00:00:00$\\) } + + # Extract the interface names from the address file paths. + awk -F/ "{if (NR > 1) printf \",\"; printf \"%s\", $5}" + } + importas -iu HARDWARE_INTERFACES HARDWARE_INTERFACES + + ${connman}/bin/connmand -ni $HARDWARE_INTERFACES + ''; + dependencies = writeText "connman-dependencies" '' + dbus + ''; + }; + + rcServices.sysctl = { + type = writeText "sysctl-type" '' + oneshot + ''; + up = writeText "sysctl-up" '' + redirfd -w 1 /proc/sys/net/ipv4/ip_forward + echo 1 + ''; + }; + + services.getty.run = writeScript "getty-run" '' + #! ${execline}/bin/execlineb -P + ${busybox}/bin/getty -i -n -l ${login} 38400 ttyS0 + ''; + + path = [ iproute iptables jq ]; + }; + + inherit (rootfs) squashfs; +} '' + mkdir $out + ln -s $linux/bzImage $out/kernel + ln -s $squashfs $out/squashfs +'' diff --git a/pkgs/servers/rust-9p/default.nix b/pkgs/servers/rust-9p/default.nix new file mode 100644 index 00000000000..115f1735d90 --- /dev/null +++ b/pkgs/servers/rust-9p/default.nix @@ -0,0 +1,34 @@ +{ stdenv, fetchFromGitHub, rustPlatform }: + +rustPlatform.buildRustPackage rec { + pname = "rust-9p"; + version = "0.0.2019-05-17"; + + src = fetchFromGitHub { + owner = "pfpacket"; + repo = pname; + rev = "01cf9c60bff0f35567d876db7be7fb86032b44eb"; + sha256 = "0mhmr1912z5nyfpcvhnlgb3v67a5n7i2n9l5abi05sfqffqssi79"; + }; + + sourceRoot = "source/example/unpfs"; + + cargoSha256 = "1d33nwj3i333a6ji3r3037mgg553lc3wsawm0pz13kbvhjf336i8"; + + RUSTC_BOOTSTRAP = 1; + + postInstall = '' + install -D -m 0444 ../../README* -t "$out/share/doc/${pname}" + install -D -m 0444 ../../LICEN* -t "$out/share/doc/${pname}" + ''; + + meta = with stdenv.lib; { + description = "9P2000.L server implementation in Rust"; + homepage = "https://github.com/pfpacket/rust-9p"; + license = licenses.bsd3; + maintainers = with maintainers; [ raskin ]; + + # macOS build fails: https://github.com/pfpacket/rust-9p/issues/7 + platforms = with platforms; linux; + }; +} diff --git a/pkgs/tools/networking/mktuntap/default.nix b/pkgs/tools/networking/mktuntap/default.nix new file mode 100644 index 00000000000..4f77c4ffc82 --- /dev/null +++ b/pkgs/tools/networking/mktuntap/default.nix @@ -0,0 +1,22 @@ +{ stdenv, lib, fetchgit }: + +stdenv.mkDerivation rec { + pname = "mktuntap"; + version = "1.0"; + + src = fetchgit { + url = "https://spectrum-os.org/git/mktuntap"; + rev = version; + sha256 = "136ichzd5811n289xqjyha81mln89yxq4a14w46ixnnx69905r47"; + }; + + installFlags = [ "prefix=$(out)" ]; + + meta = with lib; { + description = "Utility program for creating TAP and TUN devices"; + homepage = "https://spectrum-os.org/git/mktaptun"; + maintainers = with maintainers; [ qyliss ]; + license = licenses.gpl2; + platform = platforms.linux; + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index c52ad74e2ee..bb79ace50fc 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -2409,8 +2409,6 @@ in crip = callPackage ../applications/audio/crip { }; - crosvm = callPackage ../applications/virtualization/crosvm { }; - crunch = callPackage ../tools/security/crunch { }; crudini = callPackage ../tools/misc/crudini { }; @@ -7154,6 +7152,8 @@ in mkrand = callPackage ../tools/security/mkrand { }; + mktuntap = callPackage ../tools/networking/mktuntap { }; + mktemp = callPackage ../tools/security/mktemp { }; mktorrent = callPackage ../tools/misc/mktorrent { }; @@ -14917,6 +14917,11 @@ in chromaprint = callPackage ../development/libraries/chromaprint { }; + chromiumOSPackages = recurseIntoAttrs + (callPackage ../os-specific/linux/chromium-os { }); + + inherit (chromiumOSPackages) crosvm sommelier; + cl = callPackage ../development/libraries/cl { erlang = erlangR23; }; @@ -18568,6 +18573,8 @@ in spdk = callPackage ../development/libraries/spdk { }; + spectrumPackages = callPackage ../os-specific/linux/spectrum { }; + speechd = callPackage ../development/libraries/speechd { }; speech-tools = callPackage ../development/libraries/speech-tools {}; @@ -20942,7 +20949,9 @@ in lkl = callPackage ../applications/virtualization/lkl { }; inherit (callPackages ../os-specific/linux/kernel-headers { }) - linuxHeaders makeLinuxHeaders; + linuxHeaders + linuxHeadersPatches + makeLinuxHeaders; kernelPatches = callPackage ../os-specific/linux/kernel/patches.nix { }; @@ -20950,6 +20959,8 @@ in klibcShrunk = lowPrio (callPackage ../os-specific/linux/klibc/shrunk.nix { }); + linux_cros = chromiumOSPackages.linux; + linux_mptcp = linux_mptcp_95; linux_mptcp_95 = callPackage ../os-specific/linux/kernel/linux-mptcp-95.nix { @@ -21365,6 +21376,7 @@ in linux-rt = linuxPackages-rt.kernel; linux-rt_latest = linuxPackages-rt_latest.kernel; + linuxPackages_cros = linuxPackagesFor pkgs.linux_cros; linuxPackages_mptcp = linuxPackagesFor pkgs.linux_mptcp; linuxPackages_rpi1 = linuxPackagesFor pkgs.linux_rpi1; linuxPackages_rpi2 = linuxPackagesFor pkgs.linux_rpi2; @@ -24925,6 +24937,7 @@ in super-productivity = callPackage ../applications/office/super-productivity { }; wlroots = callPackage ../development/libraries/wlroots { + inherit (chromiumOSPackages) linuxHeaders; inherit (xorg) xcbutilrenderutil; }; |