summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--pkgs/applications/virtualization/crosvm/upstream-info.json19
-rw-r--r--pkgs/os-specific/linux/chromium-os/common-mk/0001-common-mk-Adjust-policy-gen-script-cmdline-args.patch109
-rw-r--r--pkgs/os-specific/linux/chromium-os/common-mk/0002-common-mk-Add-proto-library-and-its-dependencies-for.patch81
-rw-r--r--pkgs/os-specific/linux/chromium-os/common-mk/0003-common-mk-don-t-leak-source-absolute-paths.patch139
-rw-r--r--pkgs/os-specific/linux/chromium-os/common-mk/0004-common-mk-.gn-don-t-hardcode-env-path.patch23
-rw-r--r--pkgs/os-specific/linux/chromium-os/common-mk/default.nix120
-rw-r--r--pkgs/os-specific/linux/chromium-os/crosvm/default-seccomp-policy-dir.diff (renamed from pkgs/applications/virtualization/crosvm/default-seccomp-policy-dir.patch)12
-rw-r--r--pkgs/os-specific/linux/chromium-os/crosvm/default.nix (renamed from pkgs/applications/virtualization/crosvm/default.nix)25
-rw-r--r--pkgs/os-specific/linux/chromium-os/dbus-properties/default.nix9
-rw-r--r--pkgs/os-specific/linux/chromium-os/default.nix61
-rw-r--r--pkgs/os-specific/linux/chromium-os/libbrillo/0005-libbrillo-Use-a-unique_ptr-for-EVP_MD_CTX.patch86
-rw-r--r--pkgs/os-specific/linux/chromium-os/libbrillo/0006-libbrillo-Update-for-OpenSSL-1.1.patch218
-rw-r--r--pkgs/os-specific/linux/chromium-os/libbrillo/0007-libbrillo-fix-build-with-relative-platform2_root.patch26
-rw-r--r--pkgs/os-specific/linux/chromium-os/libbrillo/0008-libbrillo-don-t-leak-source-absolute-paths.patch30
-rw-r--r--pkgs/os-specific/linux/chromium-os/libbrillo/0009-libbrillo-fix-build-with-no-__has_feature.patch36
-rw-r--r--pkgs/os-specific/linux/chromium-os/libbrillo/default.nix51
-rw-r--r--pkgs/os-specific/linux/chromium-os/libchrome/0001-Don-t-leak-source-absolute-paths-to-subprocesses.patch40
-rw-r--r--pkgs/os-specific/linux/chromium-os/libchrome/default.nix62
-rw-r--r--pkgs/os-specific/linux/chromium-os/modem-manager/default.nix31
-rw-r--r--pkgs/os-specific/linux/chromium-os/modem-manager/next.nix22
-rw-r--r--pkgs/os-specific/linux/chromium-os/modp_b64/0001-modp_b64-Fix-GN-build-and-add-fuzzers.patch1127
-rw-r--r--pkgs/os-specific/linux/chromium-os/modp_b64/0002-Use-regular-archives.patch36
-rw-r--r--pkgs/os-specific/linux/chromium-os/modp_b64/default.nix30
-rw-r--r--pkgs/os-specific/linux/chromium-os/protofiles/default.nix34
-rw-r--r--pkgs/os-specific/linux/chromium-os/sommelier/0010-sommelier-don-t-leak-source-absolute-paths.patch25
-rw-r--r--pkgs/os-specific/linux/chromium-os/sommelier/default.nix33
-rwxr-xr-xpkgs/os-specific/linux/chromium-os/update.py (renamed from pkgs/applications/virtualization/crosvm/update.py)66
-rw-r--r--pkgs/os-specific/linux/chromium-os/upstream-info.json55
-rw-r--r--pkgs/os-specific/linux/chromium-os/vm_protos/default.nix31
-rw-r--r--pkgs/os-specific/linux/kernel/linux-cros-4.19.nix34
-rw-r--r--pkgs/top-level/all-packages.nix10
31 files changed, 2620 insertions, 61 deletions
diff --git a/pkgs/applications/virtualization/crosvm/upstream-info.json b/pkgs/applications/virtualization/crosvm/upstream-info.json
deleted file mode 100644
index 01921f9460a..00000000000
--- a/pkgs/applications/virtualization/crosvm/upstream-info.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "version": "77.12371.0.0-rc1",
-  "components": {
-    "chromiumos/platform/crosvm": {
-      "url": "https://chromium.googlesource.com/chromiumos/platform/crosvm",
-      "rev": "f5285c647acacb4f25ef8cf9334254b976e71686",
-      "date": "2019-07-25T22:15:48+00:00",
-      "sha256": "1ccjd540xmpad082w9ri13q78wkg95xxmq38b8ybcrj4f7lsxm6w",
-      "fetchSubmodules": false
-    },
-    "chromiumos/third_party/adhd": {
-      "url": "https://chromium.googlesource.com/chromiumos/third_party/adhd",
-      "rev": "a1c0d93d991daffb042b979ac807bbe9c1f9a3ee",
-      "date": "2019-07-25T20:38:50-07:00",
-      "sha256": "11bijqd876adarq96syywn6znfbiflqssgb2j4w032iw2vfnnsyy",
-      "fetchSubmodules": false
-    }
-  }
-}
diff --git a/pkgs/os-specific/linux/chromium-os/common-mk/0001-common-mk-Adjust-policy-gen-script-cmdline-args.patch b/pkgs/os-specific/linux/chromium-os/common-mk/0001-common-mk-Adjust-policy-gen-script-cmdline-args.patch
new file mode 100644
index 00000000000..779243944d2
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/common-mk/0001-common-mk-Adjust-policy-gen-script-cmdline-args.patch
@@ -0,0 +1,109 @@
+From fc07988a1837ea947af231d9371a7d7b96618f52 Mon Sep 17 00:00:00 2001
+From: Pavol Marko <pmarko@google.com>
+Date: Wed, 4 Sep 2019 15:21:46 +0200
+Subject: [PATCH 01/10] common-mk: Adjust policy gen script cmdline args
+
+The cmdline args interface of the policy source generation script
+'generate_policy_source.py' has changed on the Chromium side as of
+CL:1687818. Change invocations accordingly.
+While here, remove the targets 'cloud_policy_proto_generator' /
+'user_policy-protos' of common-mk/external_dependencies.gyp as the
+usages have been migrated to gn.
+
+BUG=chromium:981128
+TEST=build_packages
+
+Cq-Depend: chromium:1786282
+Change-Id: I308465451c6cee96319ea5ec104a799f1761d3ab
+Reviewed-on: https://chromium-review.googlesource.com/1785600
+Tested-by: Pavol Marko <pmarko@chromium.org>
+Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
+Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
+Reviewed-by: Mike Frysinger <vapier@chromium.org>
+Reviewed-by: Pavol Marko <pmarko@chromium.org>
+---
+ common-mk/external_dependencies.gyp      | 42 ------------------------
+ common-mk/external_dependencies/BUILD.gn |  7 ++--
+ 2 files changed, 3 insertions(+), 46 deletions(-)
+
+diff --git a/common-mk/external_dependencies.gyp b/common-mk/external_dependencies.gyp
+index 34eaa59ce..751f8566d 100644
+--- a/common-mk/external_dependencies.gyp
++++ b/common-mk/external_dependencies.gyp
+@@ -49,33 +49,6 @@
+       ],
+       'includes': ['xml2cpp.gypi'],
+     },
+-    {
+-      'target_name': 'cloud_policy_proto_generator',
+-      'type': 'none',
+-      'hard_dependency': 1,
+-      'variables': {
+-        'policy_tools_dir': '<(sysroot)/usr/share/policy_tools',
+-        'policy_resources_dir': '<(sysroot)/usr/share/policy_resources',
+-        'proto_out_dir': '<(SHARED_INTERMEDIATE_DIR)/proto',
+-      },
+-      'actions': [{
+-        'action_name': 'run_generate_script',
+-        'inputs': [
+-          '<(policy_tools_dir)/generate_policy_source.py',
+-          '<(policy_resources_dir)/policy_templates.json',
+-          '<(policy_resources_dir)/VERSION',
+-        ],
+-        'outputs': [ '<(proto_out_dir)/cloud_policy.proto' ],
+-        'action': [
+-          'python', '<(policy_tools_dir)/generate_policy_source.py',
+-          '--cloud-policy-protobuf=<(proto_out_dir)/cloud_policy.proto',
+-          '<(policy_resources_dir)/VERSION',
+-          '<(OS)',
+-          '1',         # chromeos-flag
+-          '<(policy_resources_dir)/policy_templates.json',
+-        ],
+-      }],
+-    },
+     {
+       'target_name': 'policy-protos',
+       'type': 'static_library',
+@@ -95,21 +68,6 @@
+       ],
+       'includes': ['protoc.gypi'],
+     },
+-    {
+-      'target_name': 'user_policy-protos',
+-      'type': 'static_library',
+-      'variables': {
+-        'proto_in_dir': '<(SHARED_INTERMEDIATE_DIR)/proto',
+-        'proto_out_dir': 'include/bindings',
+-      },
+-      'dependencies': [
+-        'cloud_policy_proto_generator',
+-      ],
+-      'sources': [
+-        '<(proto_in_dir)/cloud_policy.proto',
+-      ],
+-      'includes': ['protoc.gypi'],
+-    },
+     {
+       'target_name': 'install_attributes-proto',
+       'type': 'static_library',
+diff --git a/common-mk/external_dependencies/BUILD.gn b/common-mk/external_dependencies/BUILD.gn
+index 61774bf8f..4ec1665e3 100644
+--- a/common-mk/external_dependencies/BUILD.gn
++++ b/common-mk/external_dependencies/BUILD.gn
+@@ -59,10 +59,9 @@ action("cloud_policy_proto_generator") {
+   ]
+   args = [
+     "--cloud-policy-protobuf=${proto_out_dir}/cloud_policy.proto",
+-    "${policy_resources_dir}/VERSION",
+-    "${OS}",
+-    "1",  # chromeos-flag
+-    "${policy_resources_dir}/policy_templates.json",
++    "--chrome-version-file=${policy_resources_dir}/VERSION",
++    "--target-platform=chromeos",
++    "--policy-templates-file=${policy_resources_dir}/policy_templates.json",
+   ]
+ }
+ 
+-- 
+2.23.0
+
diff --git a/pkgs/os-specific/linux/chromium-os/common-mk/0002-common-mk-Add-proto-library-and-its-dependencies-for.patch b/pkgs/os-specific/linux/chromium-os/common-mk/0002-common-mk-Add-proto-library-and-its-dependencies-for.patch
new file mode 100644
index 00000000000..9de058b178a
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/common-mk/0002-common-mk-Add-proto-library-and-its-dependencies-for.patch
@@ -0,0 +1,81 @@
+From e0ed9db1d24ad7df27146f37895563f8ebc4d613 Mon Sep 17 00:00:00 2001
+From: Amr Aboelkher <amraboelkher@google.com>
+Date: Wed, 2 Oct 2019 18:08:08 +0200
+Subject: [PATCH 02/10] common-mk: Add proto library and its dependencies for
+ policy common definitions
+
+BUG=chromium:1009436,chromium:1006077,chromium:552439
+TEST=precq passes
+
+Cq-Depend: chromium:1833618
+Change-Id: I12e2f15afba615cd4395eb5818f6ff370d187c73
+Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/1835953
+Tested-by: Amr Aboelkher <amraboelkher@google.com>
+Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
+Reviewed-by: Mike Frysinger <vapier@chromium.org>
+---
+ common-mk/external_dependencies/BUILD.gn | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/common-mk/external_dependencies/BUILD.gn b/common-mk/external_dependencies/BUILD.gn
+index 4ec1665e3..61f571b38 100644
+--- a/common-mk/external_dependencies/BUILD.gn
++++ b/common-mk/external_dependencies/BUILD.gn
+@@ -65,14 +65,30 @@ action("cloud_policy_proto_generator") {
+   ]
+ }
+ 
++proto_library("policy_common_definitions-protos") {
++  proto_in_dir = "${sysroot}/usr/share/protofiles"
++  proto_out_dir = "include/bindings"
++  sources = [
++    "${proto_in_dir}/policy_common_definitions.proto",
++  ]
++
++  # policy-protos.a is used by a shared_libary object: https://crbug.com/715795
++  # Build it with '-fPIC' instead of '-fPIE'.
++  configs = [ "//common-mk:pic" ]
++}
++
+ proto_library("policy-protos") {
+   proto_in_dir = "${sysroot}/usr/share/protofiles"
+   proto_out_dir = "include/bindings"
++  proto_lib_dirs = [ "${sysroot}/usr/share/protofiles" ]
+   sources = [
+     "${proto_in_dir}/chrome_device_policy.proto",
+     "${proto_in_dir}/chrome_extension_policy.proto",
+     "${proto_in_dir}/device_management_backend.proto",
+   ]
++  public_deps = [
++    ":policy_common_definitions-protos",
++  ]
+ 
+   # policy-protos.a is used by a shared_libary object: https://crbug.com/715795
+   # Build it with '-fPIC' instead of '-fPIE'.
+@@ -88,18 +104,23 @@ goproto_library("policy-goprotos") {
+     "${proto_in_dir}/chrome_device_policy.proto",
+     "${proto_in_dir}/chrome_extension_policy.proto",
+     "${proto_in_dir}/device_management_backend.proto",
++    "${proto_in_dir}/policy_common_definitions.proto",
+   ]
+ }
+ 
+ proto_library("user_policy-protos") {
+   proto_in_dir = "${target_gen_dir}/proto"
+   proto_out_dir = "include/bindings"
++  proto_lib_dirs = [ "${sysroot}/usr/share/protofiles" ]
+   sources = [
+     "${proto_in_dir}/cloud_policy.proto",
+   ]
+   deps = [
+     ":cloud_policy_proto_generator",
+   ]
++  public_deps = [
++    ":policy_common_definitions-protos",
++  ]
+ }
+ 
+ proto_library("install_attributes-proto") {
+-- 
+2.23.0
+
diff --git a/pkgs/os-specific/linux/chromium-os/common-mk/0003-common-mk-don-t-leak-source-absolute-paths.patch b/pkgs/os-specific/linux/chromium-os/common-mk/0003-common-mk-don-t-leak-source-absolute-paths.patch
new file mode 100644
index 00000000000..fa42631f746
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/common-mk/0003-common-mk-don-t-leak-source-absolute-paths.patch
@@ -0,0 +1,139 @@
+From b5ac444592d4bd837934d8a657d9ae8b600d7f95 Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <hi@alyssa.is>
+Date: Sun, 24 Nov 2019 16:56:11 +0000
+Subject: [PATCH 03/10] 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/pkg_config.gni                 |  7 +++----
+ common-mk/proto_library.gni              | 21 +++++++++++----------
+ 3 files changed, 16 insertions(+), 15 deletions(-)
+
+diff --git a/common-mk/external_dependencies/BUILD.gn b/common-mk/external_dependencies/BUILD.gn
+index 61f571b38..4cb7b93cf 100644
+--- a/common-mk/external_dependencies/BUILD.gn
++++ b/common-mk/external_dependencies/BUILD.gn
+@@ -47,6 +47,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"
+@@ -58,7 +59,7 @@ action("cloud_policy_proto_generator") {
+     "${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/pkg_config.gni b/common-mk/pkg_config.gni
+index af3c3fb4c..151c49e56 100644
+--- a/common-mk/pkg_config.gni
++++ b/common-mk/pkg_config.gni
+@@ -81,12 +81,11 @@ 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" ] + outputs + [ "--name=" + name ]
++    args = [ "--output", rebase_path(lib_path), "--name=" + name ]
+     if (defined(description)) {
+       args += [ "--description=" + description ]
+     }
+diff --git a/common-mk/proto_library.gni b/common-mk/proto_library.gni
+index 70e32cafc..f6dce2760 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,
+@@ -92,24 +92,23 @@ template("proto_library") {
+     args += [ "${proto_in_dir}/{{source_name_part}}.proto" ]
+     outputs = []
+     if (gen_python) {
+-      python_dir = "${root_gen_dir}/${proto_out_dir}/py"
+       args += [
+         "--python_out",
+-        "${python_dir}",
++        "${proto_out_dir}/py",
+       ]
+-      outputs += [ "${python_dir}/{{source_name_part}}_pb.py" ]
++      outputs += [ "${cc_dir}/py/{{source_name_part}}_pb.py" ]
+     }
+     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}" ]
+         outputs += [ "${cc_dir}/{{source_name_part}}_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}",
+       ]
+       outputs += [
+         "${cc_dir}/{{source_name_part}}.grpc.pb.cc",
+@@ -119,7 +118,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}" ]
+       outputs += [
+         "${cc_dir}/{{source_name_part}}.pb.cc",
+         "${cc_dir}/{{source_name_part}}.pb.h",
+@@ -206,7 +205,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"
+@@ -222,7 +223,7 @@ template("goproto_library") {
+       "--proto_path",
+       "${sysroot}/usr/share/proto",
+       "--go_out",
+-      "${go_out_prefix}${root_gen_dir}/${proto_out_dir}",
++      "${go_out_prefix}${proto_out_dir}",
+     ]
+     foreach(source, sources) {
+       args += [ rebase_path(source) ]
+@@ -232,7 +233,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.23.0
+
diff --git a/pkgs/os-specific/linux/chromium-os/common-mk/0004-common-mk-.gn-don-t-hardcode-env-path.patch b/pkgs/os-specific/linux/chromium-os/common-mk/0004-common-mk-.gn-don-t-hardcode-env-path.patch
new file mode 100644
index 00000000000..3e707e518cb
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/common-mk/0004-common-mk-.gn-don-t-hardcode-env-path.patch
@@ -0,0 +1,23 @@
+From 11dbc10898cef09008e4ab9d34d855a5e8c12e71 Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <hi@alyssa.is>
+Date: Sun, 24 Nov 2019 17:20:46 +0000
+Subject: [PATCH 04/10] 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 e7dba8c91..e29fcd61e 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.23.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..1ebfbfaac70
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/common-mk/default.nix
@@ -0,0 +1,120 @@
+{ 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."chromiumos/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-Adjust-policy-gen-script-cmdline-args.patch
+      ./0002-common-mk-Add-proto-library-and-its-dependencies-for.patch
+      ./0003-common-mk-don-t-leak-source-absolute-paths.patch
+      ./0004-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",' ""
+  '') + 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/applications/virtualization/crosvm/default-seccomp-policy-dir.patch b/pkgs/os-specific/linux/chromium-os/crosvm/default-seccomp-policy-dir.diff
index 46b091b3a35..f1aa50ee102 100644
--- a/pkgs/applications/virtualization/crosvm/default-seccomp-policy-dir.patch
+++ b/pkgs/os-specific/linux/chromium-os/crosvm/default-seccomp-policy-dir.diff
@@ -1,9 +1,9 @@
-diff --git a/src/main.rs b/src/main.rs
-index 81f20a7..481ebd7 100644
---- a/src/main.rs
-+++ b/src/main.rs
-@@ -158,7 +158,9 @@ impl Default for Config {
-             wayland_dmabuf: false,
+diff --git a/src/crosvm.rs b/src/crosvm.rs
+index b7055df..5989c87 100644
+--- a/src/crosvm.rs
++++ b/src/crosvm.rs
+@@ -141,7 +141,9 @@ impl Default for Config {
+             x_display: None,
              shared_dirs: Vec::new(),
              sandbox: !cfg!(feature = "default-no-sandbox"),
 -            seccomp_policy_dir: PathBuf::from(SECCOMP_POLICY_DIR),
diff --git a/pkgs/applications/virtualization/crosvm/default.nix b/pkgs/os-specific/linux/chromium-os/crosvm/default.nix
index 2681002a25d..648fef71616 100644
--- a/pkgs/applications/virtualization/crosvm/default.nix
+++ b/pkgs/os-specific/linux/chromium-os/crosvm/default.nix
@@ -1,26 +1,18 @@
-{ stdenv, rustPlatform, fetchgit, runCommand, symlinkJoin
+{ stdenv, rustPlatform, fetchFromGitiles, upstreamInfo
 , pkgconfig, minijail, dtc, libusb1, libcap
 }:
 
 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;
-  };
+  crosvmSrc = fetchFromGitiles
+    upstreamInfo.components."chromiumos/platform/crosvm";
 
+  adhdSrc = fetchFromGitiles
+    upstreamInfo.components."chromiumos/third_party/adhd";
 in
 
   rustPlatform.buildRustPackage rec {
@@ -29,16 +21,15 @@ in
 
     unpackPhase = ''
       runHook preUnpack
+
       mkdir -p chromiumos/platform chromiumos/third_party
 
       pushd chromiumos/platform
       unpackFile ${crosvmSrc}
-      mv crosvm-* crosvm
       popd
 
       pushd chromiumos/third_party
       unpackFile ${adhdSrc}
-      mv adhd-* adhd
       popd
 
       chmod -R u+w -- "$sourceRoot"
@@ -49,10 +40,10 @@ in
     sourceRoot = "chromiumos/platform/crosvm";
 
     patches = [
-      ./default-seccomp-policy-dir.patch
+      ./default-seccomp-policy-dir.diff
     ];
 
-    cargoSha256 = "16cfp79c13ng5jjcrvz00h3cg7cc9ywhjiq02vsm757knn9jgr1v";
+    cargoSha256 = "1b5i9gwrw55p89f7vwjy801q26hwyn8hd64w6qp66fl9fr7vgvbi";
 
     nativeBuildInputs = [ pkgconfig ];
 
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..2ca5f43e1b5
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/default.nix
@@ -0,0 +1,61 @@
+{ newScope, fetchFromGitiles, symlinkJoin
+, linux_4_19, makeLinuxHeaders, modemmanager
+}:
+
+let
+  self = with self; {
+    callPackage = newScope self;
+
+    upstreamInfo = with builtins; fromJSON (readFile ./upstream-info.json);
+
+    chromiumos-overlay = (fetchFromGitiles
+      upstreamInfo.components."chromiumos/overlays/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;
+    };
+
+    libbrillo = callPackage ./libbrillo { };
+
+    libchrome = callPackage ./libchrome { };
+
+    linux_4_19 = callPackage ../kernel/linux-cros-4.19.nix {
+      inherit (linux_4_19) kernelPatches;
+    };
+
+    linux = self.linux_4_19;
+
+    linuxHeaders = makeLinuxHeaders {
+      inherit (linux) version src;
+    };
+
+    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/libbrillo/0005-libbrillo-Use-a-unique_ptr-for-EVP_MD_CTX.patch b/pkgs/os-specific/linux/chromium-os/libbrillo/0005-libbrillo-Use-a-unique_ptr-for-EVP_MD_CTX.patch
new file mode 100644
index 00000000000..8833d4e91cd
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/libbrillo/0005-libbrillo-Use-a-unique_ptr-for-EVP_MD_CTX.patch
@@ -0,0 +1,86 @@
+From ed2920bc6864e044ffa5beb8a2508f4e5f5b4ce4 Mon Sep 17 00:00:00 2001
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Thu, 17 Oct 2019 20:45:53 +1100
+Subject: [PATCH 05/10] libbrillo: Use a unique_ptr for EVP_MD_CTX
+
+In OpenSSL 1.1, the EVP_MD_CTX struct will become opaque, and therefore
+it will not be possible to allocate on the stack.
+
+Replace this stack allocation with a heap allocated EVP_MD_CTX using the
+existing OpenSSL 1.0.2 create/destroy APIs, and manage its lifetime using
+a unique_ptr<>.
+
+Note: There are cases (sludge, tael, tatl), where libbrillo is built
+against a libchrome that has been built w/out libbase-crypto (ie,
+USE="-crypto").  For this reason, we don't use the equivalent
+crypto::ScopedEVP_MD_CTX type for this one instance of this in libbrillo.
+
+BUG=chromium:737445
+TEST=cros_workon --board=sarien start libbrillo
+TEST=w/ openssl-1.0.2t: FEATURES=test emerge-sarien libbrillo
+TEST=w/ openssl-1.1.0j: FEATURES=test emerge-sarien libbrillo
+  => Both build and pass all unittests
+
+Change-Id: Ic0a43b9c85fcb967c1b381b1602c03f48ac5dcef
+Reviewed-on: https://chromium-review.googlesource.com/1866378
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
+Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
+Reviewed-by: Mike Frysinger <vapier@chromium.org>
+Reviewed-by: Nick Crews <ncrews@chromium.org>
+---
+ libbrillo/policy/device_policy_impl.cc | 18 ++++++++----------
+ 1 file changed, 8 insertions(+), 10 deletions(-)
+
+diff --git a/libbrillo/policy/device_policy_impl.cc b/libbrillo/policy/device_policy_impl.cc
+index 6ba297406..e3c12f9d6 100644
+--- a/libbrillo/policy/device_policy_impl.cc
++++ b/libbrillo/policy/device_policy_impl.cc
+@@ -55,36 +55,34 @@ bool ReadPublicKeyFromFile(const base::FilePath& key_file,
+ bool VerifySignature(const std::string& signed_data,
+                      const std::string& signature,
+                      const std::string& public_key) {
+-  EVP_MD_CTX ctx;
+-  EVP_MD_CTX_init(&ctx);
++  std::unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX *)> ctx(EVP_MD_CTX_create(),
++                                                          EVP_MD_CTX_destroy);
++  if (!ctx)
++    return false;
+ 
+   const EVP_MD* digest = EVP_sha1();
+ 
+   char* key = const_cast<char*>(public_key.data());
+   BIO* bio = BIO_new_mem_buf(key, public_key.length());
+-  if (!bio) {
+-    EVP_MD_CTX_cleanup(&ctx);
++  if (!bio)
+     return false;
+-  }
+ 
+   EVP_PKEY* public_key_ssl = d2i_PUBKEY_bio(bio, nullptr);
+   if (!public_key_ssl) {
+     BIO_free_all(bio);
+-    EVP_MD_CTX_cleanup(&ctx);
+     return false;
+   }
+ 
+   const unsigned char* sig =
+       reinterpret_cast<const unsigned char*>(signature.data());
+-  int rv = EVP_VerifyInit_ex(&ctx, digest, nullptr);
++  int rv = EVP_VerifyInit_ex(ctx.get(), digest, nullptr);
+   if (rv == 1) {
+-    EVP_VerifyUpdate(&ctx, signed_data.data(), signed_data.length());
+-    rv = EVP_VerifyFinal(&ctx, sig, signature.length(), public_key_ssl);
++    EVP_VerifyUpdate(ctx.get(), signed_data.data(), signed_data.length());
++    rv = EVP_VerifyFinal(ctx.get(), sig, signature.length(), public_key_ssl);
+   }
+ 
+   EVP_PKEY_free(public_key_ssl);
+   BIO_free_all(bio);
+-  EVP_MD_CTX_cleanup(&ctx);
+ 
+   return rv == 1;
+ }
+-- 
+2.23.0
+
diff --git a/pkgs/os-specific/linux/chromium-os/libbrillo/0006-libbrillo-Update-for-OpenSSL-1.1.patch b/pkgs/os-specific/linux/chromium-os/libbrillo/0006-libbrillo-Update-for-OpenSSL-1.1.patch
new file mode 100644
index 00000000000..ef2b4b735bc
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/libbrillo/0006-libbrillo-Update-for-OpenSSL-1.1.patch
@@ -0,0 +1,218 @@
+From 1c81e92e7a983c2f9fff7bd56ce769f2edb59a59 Mon Sep 17 00:00:00 2001
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Mon, 3 Jun 2019 16:46:17 -0600
+Subject: [PATCH 06/10] libbrillo: Update for OpenSSL 1.1
+
+OpenSSL 1.1 has made significant non-backwards compatible changes to its
+API as outlined in:
+https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes
+
+Note: There are cases (sludge, tael, tatl), where libbrillo is built
+against a libchrome that has been built w/out libbase-crypto (ie,
+USE="-crypto").  For this reason, we don't use its libcrypto-compat.h.
+
+BUG=chromium:737445
+TEST=cros_workon --board=sarien start libbrillo
+TEST=w/ openssl-1.0.2t: FEATURES=test emerge-sarien libbrillo
+TEST=w/ openssl-1.1.0j: FEATURES=test emerge-sarien libbrillo
+ => Both build and pass all unittests
+
+Change-Id: I911c733e63ccbe58b7d9ef6d8e84c9e121056725
+Reviewed-on: https://chromium-review.googlesource.com/1641754
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
+Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
+Reviewed-by: Mike Frysinger <vapier@chromium.org>
+Reviewed-by: Nick Crews <ncrews@chromium.org>
+---
+ .../brillo/streams/openssl_stream_bio.cc      | 75 ++++++++++++++++---
+ libbrillo/brillo/streams/tls_stream.cc        |  7 +-
+ libbrillo/policy/device_policy_impl.cc        | 10 ++-
+ 3 files changed, 77 insertions(+), 15 deletions(-)
+
+diff --git a/libbrillo/brillo/streams/openssl_stream_bio.cc b/libbrillo/brillo/streams/openssl_stream_bio.cc
+index a63d9c0cc..478b11233 100644
+--- a/libbrillo/brillo/streams/openssl_stream_bio.cc
++++ b/libbrillo/brillo/streams/openssl_stream_bio.cc
+@@ -13,9 +13,32 @@ namespace brillo {
+ 
+ namespace {
+ 
++// TODO(crbug.com/984789): Remove once support for OpenSSL <1.1 is dropped.
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++static void BIO_set_data(BIO* a, void* ptr) {
++  a->ptr = ptr;
++}
++
++static void* BIO_get_data(BIO* a) {
++  return a->ptr;
++}
++
++static void BIO_set_init(BIO* a, int init) {
++  a->init = init;
++}
++
++static int BIO_get_init(BIO* a) {
++  return a->init;
++}
++
++static void BIO_set_shutdown(BIO* a, int shut) {
++  a->shutdown = shut;
++}
++#endif
++
+ // Internal functions for implementing OpenSSL BIO on brillo::Stream.
+ int stream_write(BIO* bio, const char* buf, int size) {
+-  brillo::Stream* stream = static_cast<brillo::Stream*>(bio->ptr);
++  brillo::Stream* stream = static_cast<brillo::Stream*>(BIO_get_data(bio));
+   size_t written = 0;
+   BIO_clear_retry_flags(bio);
+   if (!stream->WriteNonBlocking(buf, size, &written, nullptr))
+@@ -30,7 +53,7 @@ int stream_write(BIO* bio, const char* buf, int size) {
+ }
+ 
+ int stream_read(BIO* bio, char* buf, int size) {
+-  brillo::Stream* stream = static_cast<brillo::Stream*>(bio->ptr);
++  brillo::Stream* stream = static_cast<brillo::Stream*>(BIO_get_data(bio));
+   size_t read = 0;
+   BIO_clear_retry_flags(bio);
+   bool eos = false;
+@@ -49,16 +72,16 @@ int stream_read(BIO* bio, char* buf, int size) {
+ // NOLINTNEXTLINE(runtime/int)
+ long stream_ctrl(BIO* bio, int cmd, long /* num */, void* /* ptr */) {
+   if (cmd == BIO_CTRL_FLUSH) {
+-    brillo::Stream* stream = static_cast<brillo::Stream*>(bio->ptr);
++    brillo::Stream* stream = static_cast<brillo::Stream*>(BIO_get_data(bio));
+     return stream->FlushBlocking(nullptr) ? 1 : 0;
+   }
+   return 0;
+ }
+ 
+ int stream_new(BIO* bio) {
+-  bio->shutdown = 0;  // By default do not close underlying stream on shutdown.
+-  bio->init = 0;
+-  bio->num = -1;  // not used.
++  // By default do not close underlying stream on shutdown.
++  BIO_set_shutdown(bio, 0);
++  BIO_set_init(bio, 0);
+   return 1;
+ }
+ 
+@@ -66,13 +89,17 @@ int stream_free(BIO* bio) {
+   if (!bio)
+     return 0;
+ 
+-  if (bio->init) {
+-    bio->ptr = nullptr;
+-    bio->init = 0;
++  if (BIO_get_init(bio)) {
++    BIO_set_data(bio, nullptr);
++    BIO_set_init(bio, 0);
+   }
+   return 1;
+ }
+ 
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++// TODO(crbug.com/984789): Remove #ifdef once support for OpenSSL <1.1 is
++// dropped.
++
+ // BIO_METHOD structure describing the BIO built on top of brillo::Stream.
+ BIO_METHOD stream_method = {
+     0x7F | BIO_TYPE_SOURCE_SINK,  // type: 0x7F is an arbitrary unused type ID.
+@@ -87,13 +114,37 @@ BIO_METHOD stream_method = {
+     nullptr,       // callback function, not used
+ };
+ 
++BIO_METHOD* stream_get_method() {
++  return &stream_method;
++}
++
++#else
++
++BIO_METHOD* stream_get_method() {
++  static BIO_METHOD* stream_method;
++
++  if (!stream_method) {
++    stream_method = BIO_meth_new(BIO_get_new_index() | BIO_TYPE_SOURCE_SINK,
++                                 "stream");
++    BIO_meth_set_write(stream_method, stream_write);
++    BIO_meth_set_read(stream_method, stream_read);
++    BIO_meth_set_ctrl(stream_method, stream_ctrl);
++    BIO_meth_set_create(stream_method, stream_new);
++    BIO_meth_set_destroy(stream_method, stream_free);
++  }
++
++  return stream_method;
++}
++
++#endif
++
+ }  // anonymous namespace
+ 
+ BIO* BIO_new_stream(brillo::Stream* stream) {
+-  BIO* bio = BIO_new(&stream_method);
++  BIO* bio = BIO_new(stream_get_method());
+   if (bio) {
+-    bio->ptr = stream;
+-    bio->init = 1;
++    BIO_set_data(bio, stream);
++    BIO_set_init(bio, 1);
+   }
+   return bio;
+ }
+diff --git a/libbrillo/brillo/streams/tls_stream.cc b/libbrillo/brillo/streams/tls_stream.cc
+index 603bd1d54..cc63258db 100644
+--- a/libbrillo/brillo/streams/tls_stream.cc
++++ b/libbrillo/brillo/streams/tls_stream.cc
+@@ -68,6 +68,11 @@ const char kCACertificatePath[] =
+ 
+ namespace brillo {
+ 
++// TODO(crbug.com/984789): Remove once support for OpenSSL <1.1 is dropped.
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++#define TLS_client_method() TLSv1_2_client_method()
++#endif
++
+ // Helper implementation of TLS stream used to hide most of OpenSSL inner
+ // workings from the users of brillo::TlsStream.
+ class TlsStream::TlsStreamImpl {
+@@ -342,7 +347,7 @@ bool TlsStream::TlsStreamImpl::Init(StreamPtr socket,
+                                     const base::Closure& success_callback,
+                                     const Stream::ErrorCallback& error_callback,
+                                     ErrorPtr* error) {
+-  ctx_.reset(SSL_CTX_new(TLSv1_2_client_method()));
++  ctx_.reset(SSL_CTX_new(TLS_client_method()));
+   if (!ctx_)
+     return ReportError(error, FROM_HERE, "Cannot create SSL_CTX");
+ 
+diff --git a/libbrillo/policy/device_policy_impl.cc b/libbrillo/policy/device_policy_impl.cc
+index e3c12f9d6..0c112a1b9 100644
+--- a/libbrillo/policy/device_policy_impl.cc
++++ b/libbrillo/policy/device_policy_impl.cc
+@@ -30,6 +30,12 @@ namespace em = enterprise_management;
+ 
+ namespace policy {
+ 
++// TODO(crbug.com/984789): Remove once support for OpenSSL <1.1 is dropped.
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++#define EVP_MD_CTX_new EVP_MD_CTX_create
++#define EVP_MD_CTX_free EVP_MD_CTX_destroy
++#endif
++
+ // Maximum value of RollbackAllowedMilestones policy.
+ const int kMaxRollbackAllowedMilestones = 4;
+ 
+@@ -55,8 +61,8 @@ bool ReadPublicKeyFromFile(const base::FilePath& key_file,
+ bool VerifySignature(const std::string& signed_data,
+                      const std::string& signature,
+                      const std::string& public_key) {
+-  std::unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX *)> ctx(EVP_MD_CTX_create(),
+-                                                          EVP_MD_CTX_destroy);
++  std::unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX *)> ctx(EVP_MD_CTX_new(),
++                                                          EVP_MD_CTX_free);
+   if (!ctx)
+     return false;
+ 
+-- 
+2.23.0
+
diff --git a/pkgs/os-specific/linux/chromium-os/libbrillo/0007-libbrillo-fix-build-with-relative-platform2_root.patch b/pkgs/os-specific/linux/chromium-os/libbrillo/0007-libbrillo-fix-build-with-relative-platform2_root.patch
new file mode 100644
index 00000000000..c476c812450
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/libbrillo/0007-libbrillo-fix-build-with-relative-platform2_root.patch
@@ -0,0 +1,26 @@
+From 16960cbb59804aebc4b7dd5f746d2452c8a1edd0 Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <hi@alyssa.is>
+Date: Sun, 1 Dec 2019 22:11:39 +0000
+Subject: [PATCH 07/10] libbrillo: fix build with relative platform2_root
+
+---
+ libbrillo/BUILD.gn | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/libbrillo/BUILD.gn b/libbrillo/BUILD.gn
+index e475692ab..c3ca0054b 100644
+--- a/libbrillo/BUILD.gn
++++ b/libbrillo/BUILD.gn
+@@ -355,7 +355,8 @@ shared_library("libpolicy-${libbase_ver}") {
+     "openssl",
+     "protobuf-lite",
+   ]
+-  ldflags = [ "-Wl,--version-script,${platform2_root}/libbrillo/libpolicy.ver" ]
++  libpolicy_ver = rebase_path("//libbrillo/libpolicy.ver")
++  ldflags = [ "-Wl,--version-script,${libpolicy_ver}" ]
+   sources = [
+     "policy/device_policy.cc",
+     "policy/device_policy_impl.cc",
+-- 
+2.23.0
+
diff --git a/pkgs/os-specific/linux/chromium-os/libbrillo/0008-libbrillo-don-t-leak-source-absolute-paths.patch b/pkgs/os-specific/linux/chromium-os/libbrillo/0008-libbrillo-don-t-leak-source-absolute-paths.patch
new file mode 100644
index 00000000000..f9832eebb07
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/libbrillo/0008-libbrillo-don-t-leak-source-absolute-paths.patch
@@ -0,0 +1,30 @@
+From 308678664652685d48dccc4ea6d55195a307e36d Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <hi@alyssa.is>
+Date: Sun, 1 Dec 2019 14:55:21 +0000
+Subject: [PATCH 08/10] libbrillo: don't leak source-absolute paths
+
+---
+ libbrillo/BUILD.gn | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/libbrillo/BUILD.gn b/libbrillo/BUILD.gn
+index c3ca0054b..4ae5aced0 100644
+--- a/libbrillo/BUILD.gn
++++ b/libbrillo/BUILD.gn
+@@ -260,10 +260,9 @@ action("libbrillo-${libbase_ver}") {
+     deps += [ ":lib" + sublib.library_name ]
+   }
+   script = "//common-mk/write_args.py"
+-  outputs = [
+-    "${root_out_dir}/lib/libbrillo-${libbase_ver}.so",
+-  ]
+-  args = [ "--output" ] + outputs + [ "--" ] + [
++  lib_path = "${root_out_dir}/lib/libbrillo-${libbase_ver}.so"
++  outputs = [ lib_path ]
++  args = [ "--output", rebase_path(lib_path), "--",
+            "GROUP",
+            "(",
+            "AS_NEEDED",
+-- 
+2.23.0
+
diff --git a/pkgs/os-specific/linux/chromium-os/libbrillo/0009-libbrillo-fix-build-with-no-__has_feature.patch b/pkgs/os-specific/linux/chromium-os/libbrillo/0009-libbrillo-fix-build-with-no-__has_feature.patch
new file mode 100644
index 00000000000..3d4c1542693
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/libbrillo/0009-libbrillo-fix-build-with-no-__has_feature.patch
@@ -0,0 +1,36 @@
+From dce65ab2cb0bac44cf5a133aface2acf9f0b2367 Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <hi@alyssa.is>
+Date: Sun, 1 Dec 2019 14:57:01 +0000
+Subject: [PATCH 09/10] libbrillo: fix build with no __has_feature
+
+---
+ libbrillo/brillo/asan.h | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/libbrillo/brillo/asan.h b/libbrillo/brillo/asan.h
+index d29932a82..0d707467f 100644
+--- a/libbrillo/brillo/asan.h
++++ b/libbrillo/brillo/asan.h
+@@ -7,13 +7,17 @@
+ #ifndef LIBBRILLO_BRILLO_ASAN_H_
+ #define LIBBRILLO_BRILLO_ASAN_H_
+ 
+-#if defined(__has_feature) && __has_feature(address_sanitizer)
++#if defined(__has_feature)
++#if __has_feature(address_sanitizer)
+ // ASan is enabled.
+ #define BRILLO_ASAN_BUILD 1
+ // Provide BRILLO_DISABLE_ASAN hook to disable ASan.
+ // Put this in front on functions or global variables where required.
+ #define BRILLO_DISABLE_ASAN __attribute__((no_sanitize("address")))
+-#else
++#endif
++#endif
++
++#ifndef BRILLO_DISABLE_ASAN
+ #define BRILLO_DISABLE_ASAN
+ #endif
+ 
+-- 
+2.23.0
+
diff --git a/pkgs/os-specific/linux/chromium-os/libbrillo/default.nix b/pkgs/os-specific/linux/chromium-os/libbrillo/default.nix
new file mode 100644
index 00000000000..c5bb961d0cd
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/libbrillo/default.nix
@@ -0,0 +1,51 @@
+{ common-mk, lib
+, dbus_cplusplus, go-protobuf, protofiles, dbus-interfaces
+, libchrome, curl, minijail, protobuf, glib, gtest, modp_b64
+}:
+
+common-mk {
+  platformSubdir = "libbrillo";
+
+  platform2Patches = [
+    ./0005-libbrillo-Use-a-unique_ptr-for-EVP_MD_CTX.patch
+    ./0006-libbrillo-Update-for-OpenSSL-1.1.patch
+    ./0007-libbrillo-fix-build-with-relative-platform2_root.patch
+    ./0008-libbrillo-don-t-leak-source-absolute-paths.patch
+    ./0009-libbrillo-fix-build-with-no-__has_feature.patch
+  ];
+
+  nativeBuildInputs = [ dbus_cplusplus go-protobuf ];
+  buildInputs = [ libchrome curl minijail protobuf glib gtest modp_b64 ];
+
+  NIX_CFLAGS_COMPILE = [ "-Wno-error=sign-compare" ];
+
+  postPatch = ''
+    substituteInPlace common-mk/external_dependencies/BUILD.gn \
+        --replace '"''${sysroot}/usr/share/policy_tools"' '"${protofiles}/share/policy_tools"' \
+        --replace '"''${sysroot}/usr/share/policy_resources"' '"${protofiles}/share/policy_resources"' \
+        --replace '"''${sysroot}/usr/share/dbus-1/interfaces/"' '"${dbus-interfaces}/share/dbus-1/interfaces/"' \
+        --replace '"''${sysroot}/usr/include/proto"' '"${protofiles}/include/proto"' \
+        --replace '"''${sysroot}/usr/share/protofiles"' '"${protofiles}/share/protofiles"'
+  '';
+
+  installPhase = ''
+    mkdir -p $out/lib/pkgconfig $out/include/install_attributes
+
+    install lib/*.so $out/lib
+    install libbrillo*.a $out/lib
+    install -m 0644 obj/libbrillo/*.pc $out/lib/pkgconfig
+
+    pushd ../../libbrillo
+    find brillo policy -name '*.h' -print0 \
+        | xargs -t -0 tar -c \
+        | tar -C $out/include -x
+    install -m 0644 install_attributes/libinstallattributes.h \
+        $out/include/install_attributes
+    popd
+  '';
+
+  meta = with lib; {
+    description = "Chromium OS utility library";
+    maintainers = with maintainers; [ qyliss ];
+  };
+}
diff --git a/pkgs/os-specific/linux/chromium-os/libchrome/0001-Don-t-leak-source-absolute-paths-to-subprocesses.patch b/pkgs/os-specific/linux/chromium-os/libchrome/0001-Don-t-leak-source-absolute-paths-to-subprocesses.patch
new file mode 100644
index 00000000000..da58c4b15a7
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/libchrome/0001-Don-t-leak-source-absolute-paths-to-subprocesses.patch
@@ -0,0 +1,40 @@
+From a4499cdec93f1b1fd8c2a9db02244d667d9c7e11 Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <hi@alyssa.is>
+Date: Wed, 27 Nov 2019 17:10:18 +0000
+Subject: [PATCH] Don't leak source-absolute paths to subprocesses
+
+---
+ BUILD.gn | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/BUILD.gn b/BUILD.gn
+index 4477a86..5869e1f 100644
+--- a/BUILD.gn
++++ b/BUILD.gn
+@@ -466,8 +466,9 @@ action("base") {
+   }
+ 
+   script = "//common-mk/write_args.py"
+-  outputs = [ "${root_out_dir}/lib/lib${target_name}-${libbase_ver}.so" ]
+-  args = [ "--output" ] + outputs + [ "--" ] + [
++  lib_path = "${root_out_dir}/lib/lib${target_name}-${libbase_ver}.so"
++  outputs = [ lib_path ]
++  args = [ "--output", rebase_path(lib_path), "--" ] + [
+     "GROUP", "(", "AS_NEEDED", "(",
+   ]
+   foreach(attr, libbase_sublibs) {
+@@ -524,8 +525,9 @@ action("base-test") {
+   }
+ 
+   script = "//common-mk/write_args.py"
+-  outputs = [ "${root_out_dir}/lib${target_name}-${libbase_ver}.a" ]
+-  args = [ "--output" ] + outputs + [ "--" ] + [
++  lib_path = "${root_out_dir}/lib/lib${target_name}-${libbase_ver}.so"
++  outputs = [ lib_path ]
++  args = [ "--output", rebase_path(lib_path), "--" ] + [
+     "GROUP", "(", "AS_NEEDED", "(",
+   ]
+   foreach(attr, libbase_sublibs) {
+-- 
+2.23.0
+
diff --git a/pkgs/os-specific/linux/chromium-os/libchrome/default.nix b/pkgs/os-specific/linux/chromium-os/libchrome/default.nix
new file mode 100644
index 00000000000..3aae238e243
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/libchrome/default.nix
@@ -0,0 +1,62 @@
+{ common-mk, stdenv, lib, fetchFromGitiles, upstreamInfo
+, glib, libevent, gmock, modp_b64, chromiumos-overlay
+}:
+
+let
+  versionData = upstreamInfo.components."aosp/platform/external/libchrome";
+in
+
+common-mk rec {
+  platformSubdir = "libchrome";
+  inherit (versionData) version;
+
+  src = fetchFromGitiles { inherit (versionData) name url rev sha256; };
+
+  NIX_CFLAGS_COMPILE = [
+    "-Wno-error=attributes"
+    "-Wno-error=dangling-else"
+    "-Wno-error=implicit-fallthrough"
+    "-Wno-error=unused-function"
+  ];
+
+  buildInputs = [ glib libevent gmock modp_b64 ];
+
+  patches = [
+    ./0001-Don-t-leak-source-absolute-paths-to-subprocesses.patch
+    "${chromiumos-overlay}/chromeos-base/libchrome/files/libchrome-462023-Introduce-ValueReferenceAdapter-for-gracef.patch"
+    "${chromiumos-overlay}/chromeos-base/libchrome/files/libchrome-462023-libchrome-add-alias-from-base-Location-base-GetProgr.patch"
+  ];
+
+  postPatch = ''
+    substituteInPlace libchrome/BUILD.gn \
+        --replace '/usr/include/base-''${libbase_ver}' \
+                  "$out/include/base-\''${libbase_ver}"
+  '' + (if stdenv.cc.isClang then ''
+    substituteInPlace libchrome/BUILD.gn \
+        --replace '"-Xclang-only=-Wno-char-subscripts",' ""
+  '' else ''
+    substituteInPlace libchrome/BUILD.gn \
+        --replace "-Xclang-only=" "" \
+        --replace '"-Wno-deprecated-register",' ""
+  '');
+
+  installPhase = ''
+    mkdir -p $out/lib/pkgconfig
+    install lib/libbase*-$version.so $out/lib
+    install obj/libchrome/libchrome*-$version.pc $out/lib/pkgconfig
+
+    pushd ../../libchrome
+    mkdir -p $out/include/base-$version
+    find . -name '*.h' -print0 \
+        | xargs -0 tar -c \
+        | tar -C $out/include/base-$version -x
+    popd
+  '';
+
+  meta = with lib; {
+    description = "Chromium project utility library";
+    license = licenses.bsd3;
+    maintainers = with maintainers; [ qyliss ];
+    platform = platforms.all;
+  };
+}
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..c6a5a44b67e
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/modem-manager/default.nix
@@ -0,0 +1,31 @@
+{ 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";
+    };
+
+    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..8ad0e63bf9c
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/modem-manager/next.nix
@@ -0,0 +1,22 @@
+{ modemmanager, lib, fetchFromGitiles, upstreamInfo, autoreconfHook, libxslt }:
+
+modemmanager.overrideAttrs (
+  { pname, nativeBuildInputs ? [], passthru ? {}, meta ? {}, ... }:
+  {
+    pname = "${pname}-chromiumos-next-unstable";
+    version = "2019-10-17";
+
+    src = fetchFromGitiles
+      upstreamInfo.components."chromiumos/third_party/modemmanager-next";
+
+    nativeBuildInputs = nativeBuildInputs ++ [ autoreconfHook 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/0001-modp_b64-Fix-GN-build-and-add-fuzzers.patch b/pkgs/os-specific/linux/chromium-os/modp_b64/0001-modp_b64-Fix-GN-build-and-add-fuzzers.patch
new file mode 100644
index 00000000000..b5321c9a48c
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/modp_b64/0001-modp_b64-Fix-GN-build-and-add-fuzzers.patch
@@ -0,0 +1,1127 @@
+From 832ee65ffff7353e88bf622e2d14e22e991ce698 Mon Sep 17 00:00:00 2001
+From: Manoj Gupta <manojgupta@google.com>
+Date: Wed, 9 Oct 2019 12:40:18 -0700
+Subject: [PATCH 1/2] modp_b64: Fix GN build and add fuzzers.
+
+modp_b64 is currently build with Makefile.
+Fix the BUILD.gn so that it can be used and remove
+Makefile usage.
+Also add two fuzzers for encode and decode routines.
+
+BUG=chromium:1012803
+TEST=GN build work with modified ebuild.
+
+Cq-Depend: chromium:1850664
+Change-Id: I1756237d91630ea7e18e7c3ed055d2b3b532de0d
+---
+ BUILD.gn                          |  53 +-
+ Makefile                          |  20 -
+ OWNERS.fuzzer                     |   1 +
+ common.mk                         | 941 ------------------------------
+ fuzzers/modp_b64_decode_fuzzer.cc |  17 +
+ fuzzers/modp_b64_encode_fuzzer.cc |  17 +
+ 6 files changed, 84 insertions(+), 965 deletions(-)
+ delete mode 100644 Makefile
+ create mode 100644 OWNERS.fuzzer
+ delete mode 100644 common.mk
+ create mode 100644 fuzzers/modp_b64_decode_fuzzer.cc
+ create mode 100644 fuzzers/modp_b64_encode_fuzzer.cc
+
+diff --git a/BUILD.gn b/BUILD.gn
+index cd322ac..b2fe97d 100644
+--- a/BUILD.gn
++++ b/BUILD.gn
+@@ -1,15 +1,60 @@
+-# Copyright (c) 2013 The Chromium Authors. All rights reserved.
++# Copyright 2013 The Chromium Authors. All rights reserved.
+ # Use of this source code is governed by a BSD-style license that can be
+ # found in the LICENSE file.
+ 
+-source_set("modp_b64") {
++group("all") {
++  deps = [
++    ":modp_b64",
++  ]
++
++  if (use.fuzzer) {
++    deps += [
++      ":modp_b64_decode_fuzzer",
++      ":modp_b64_encode_fuzzer",
++    ]
++  }
++}
++
++static_library("modp_b64") {
+   sources = [
+     "modp_b64.cc",
+     "modp_b64.h",
+     "modp_b64_data.h",
+   ]
+-
+   include_dirs = [
+-    "./modp_b64",
++    "modp_b64",
+   ]
+ }
++
++# Fuzzers.
++if (use.fuzzer) {
++  executable("modp_b64_decode_fuzzer") {
++    configs += [
++      "//common-mk/common_fuzzer",
++    ]
++    deps = [
++      ":modp_b64",
++    ]
++    sources = [
++      "fuzzers/modp_b64_decode_fuzzer.cc",
++    ]
++    include_dirs = [
++      "modp_b64",
++    ]
++  }
++
++  executable("modp_b64_encode_fuzzer") {
++    configs += [
++      "//common-mk/common_fuzzer",
++    ]
++    deps = [
++      ":modp_b64",
++    ]
++    sources = [
++      "fuzzers/modp_b64_encode_fuzzer.cc",
++    ]
++    include_dirs = [
++      "modp_b64",
++    ]
++  }
++}
+diff --git a/Makefile b/Makefile
+deleted file mode 100644
+index c33ff75..0000000
+--- a/Makefile
++++ /dev/null
+@@ -1,20 +0,0 @@
+-# Copyright (C) 2015 The Android Open Source Project
+-#
+-# Licensed under the Apache License, Version 2.0 (the "License");
+-# you may not use this file except in compliance with the License.
+-# You may obtain a copy of the License at
+-#
+-#      http://www.apache.org/licenses/LICENSE-2.0
+-#
+-# Unless required by applicable law or agreed to in writing, software
+-# distributed under the License is distributed on an "AS IS" BASIS,
+-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-# See the License for the specific language governing permissions and
+-# limitations under the License.
+-
+-include common.mk
+-
+-CXXFLAGS += -I$(SRC)/modp_b64/
+-CXX_STATIC_LIBRARY(libmodpb64.pie.a): $(CXX_OBJECTS)
+-
+-all: CXX_STATIC_LIBRARY(libmodpb64.pie.a)
+diff --git a/OWNERS.fuzzer b/OWNERS.fuzzer
+new file mode 100644
+index 0000000..62800d6
+--- /dev/null
++++ b/OWNERS.fuzzer
+@@ -0,0 +1 @@
++manojgupta@chromium.org
+diff --git a/common.mk b/common.mk
+deleted file mode 100644
+index 51ead56..0000000
+--- a/common.mk
++++ /dev/null
+@@ -1,941 +0,0 @@
+-# copyright (c) 2012 the chromium os authors. all rights reserved.
+-# use of this source code is governed by a bsd-style license that can be
+-# found in the license file.
+-#
+-# If this file is part of another source distribution, it's license may be
+-# stored in LICENSE.makefile or LICENSE.common.mk.
+-#
+-# NOTE NOTE NOTE
+-#  The authoritative common.mk is located in:
+-#    https://chromium.googlesource.com/chromiumos/platform2/+/master/common-mk
+-#  Please make all changes there, then copy into place in other repos.
+-# NOTE NOTE NOTE
+-#
+-# This file provides a common architecture for building C/C++ source trees.
+-# It uses recursive makefile inclusion to create a single make process which
+-# can be built in the source tree or with the build artifacts placed elsewhere.
+-#
+-# It is fully parallelizable for all targets, including static archives.
+-#
+-# To use:
+-# 1. Place common.mk in your top source level
+-# 2. In your top-level Makefile, place "include common.mk" at the top
+-# 3. In all subdirectories, create a 'module.mk' file that starts with:
+-#      include common.mk
+-#    And then contains the remainder of your targets.
+-# 4. All build targets should look like:
+-#    relative/path/target: relative/path/obj.o
+-#
+-# See existing makefiles for rule examples.
+-#
+-# Exported macros:
+-#   - cc_binary, cxx_binary provide standard compilation steps for binaries
+-#   - cxx_library, cc_library provide standard compilation steps for
+-#     shared objects.
+-#   All of the above optionally take an argument for extra flags.
+-#   - update_archive creates/updates a given .a target
+-#
+-# Instead of using the build macros, most users can just use wrapped targets:
+-#   - CXX_BINARY, CC_BINARY, CC_STATIC_BINARY, CXX_STATIC_BINARY
+-#   - CXX_LIBRARY, CC_LIBRARY, CC_STATIC_LIBRARY, CXX_STATIC_LIBRARY
+-#   - E.g., CXX_BINARY(mahbinary): foo.o
+-#   - object.depends targets may be used when a prerequisite is required for an
+-#     object file. Because object files result in multiple build artifacts to
+-#     handle PIC and PIE weirdness. E.g.
+-#       foo.o.depends: generated/dbus.h
+-#   - TEST(binary) or TEST(CXX_BINARY(binary)) may be used as a prerequisite
+-#     for the tests target to trigger an automated test run.
+-#   - CLEAN(file_or_dir) dependency can be added to 'clean'.
+-#
+-# If source code is being generated, rules will need to be registered for
+-# compiling the objects.  This can be done by adding one of the following
+-# to the Makefile:
+-#   - For C source files
+-#   $(eval $(call add_object_rules,sub/dir/gen_a.o sub/dir/b.o,CC,c,CFLAGS))
+-#   - For C++ source files
+-#   $(eval $(call add_object_rules,sub/dir/gen_a.o sub/dir/b.o,CXX,cc,CXXFLAGS))
+-#
+-# Exported targets meant to have prerequisites added to:
+-#  - all - Your desired targets should be given
+-#  - tests - Any TEST(test_binary) targets should be given
+-#  - FORCE - force the given target to run regardless of changes
+-#            In most cases, using .PHONY is preferred.
+-#
+-# Possible command line variables:
+-#   - COLOR=[0|1] to set ANSI color output (default: 1)
+-#   - VERBOSE=[0|1] to hide/show commands (default: 0)
+-#   - MODE=[opt|dbg|profiling] (default: opt)
+-#          opt - Enable optimizations for release builds
+-#          dbg - Turn down optimization for debugging
+-#          profiling - Turn off optimization and turn on profiling/coverage
+-#                      support.
+-#   - ARCH=[x86|arm|supported qemu name] (default: from portage or uname -m)
+-#   - SPLITDEBUG=[0|1] splits debug info in target.debug (default: 0)
+-#        If NOSTRIP=1, SPLITDEBUG will never strip the final emitted objects.
+-#   - NOSTRIP=[0|1] determines if binaries are stripped. (default: 1)
+-#        NOSTRIP=0 and MODE=opt will also drop -g from the CFLAGS.
+-#   - VALGRIND=[0|1] runs tests under valgrind (default: 0)
+-#   - OUT=/path/to/builddir puts all output in given path (default: $PWD)
+-#   - VALGRIND_ARGS="" supplies extra memcheck arguments
+-#
+-# Per-target(-ish) variable:
+-#   - NEEDS_ROOT=[0|1] allows a TEST() target to run with root.
+-#     Default is 0 unless it is running under QEmu.
+-#   - NEEDS_MOUNTS=[0|1] allows a TEST() target running on QEmu to get
+-#     setup mounts in the $(SYSROOT)
+-#
+-# Caveats:
+-# - Directories or files with spaces in them DO NOT get along with GNU Make.
+-#   If you need them, all uses of dir/notdir/etc will need to have magic
+-#   wrappers.  Proceed at risk to your own sanity.
+-# - External CXXFLAGS and CFLAGS should be passed via the environment since
+-#   this file does not use 'override' to control them.
+-# - Our version of GNU Make doesn't seem to support the 'private' variable
+-#   annotation, so you can't tag a variable private on a wrapping target.
+-
+-# Behavior configuration variables
+-SPLITDEBUG ?= 0
+-NOSTRIP ?= 1
+-VALGRIND ?= 0
+-COLOR ?= 1
+-VERBOSE ?= 0
+-MODE ?= opt
+-CXXEXCEPTIONS ?= 0
+-ARCH ?= $(shell uname -m)
+-
+-# Put objects in a separate tree based on makefile locations
+-# This means you can build a tree without touching it:
+-#   make -C $SRCDIR  # will create ./build-$(MODE)
+-# Or
+-#   make -C $SRCDIR OUT=$PWD
+-# This variable is extended on subdir calls and doesn't need to be re-called.
+-OUT ?= $(PWD)/
+-
+-# Make OUT now so we can use realpath.
+-$(shell mkdir -p "$(OUT)")
+-
+-# TODO(wad) Relative paths are resolved against SRC and not the calling dir.
+-# Ensure a command-line supplied OUT has a slash
+-override OUT := $(realpath $(OUT))/
+-
+-# SRC is not meant to be set by the end user, but during make call relocation.
+-# $(PWD) != $(CURDIR) all the time.
+-export SRC ?= $(CURDIR)
+-
+-# If BASE_VER is not set, read the libchrome revision number from
+-# common-mk/BASE_VER file.
+-ifeq ($(strip $(BASE_VER)),)
+-BASE_VER := $(shell cat $(SRC)/../common-mk/BASE_VER)
+-endif
+-$(info Using BASE_VER=$(BASE_VER))
+-
+-# Re-start in the $(OUT) directory if we're not there.
+-# We may be invoked using -C or bare and we need to ensure behavior
+-# is consistent so we check both PWD vs OUT and PWD vs CURDIR.
+-override RELOCATE_BUILD := 0
+-ifneq (${PWD}/,${OUT})
+-override RELOCATE_BUILD := 1
+-endif
+-# Make sure we're running with no builtin targets. They cause
+-# leakage and mayhem!
+-ifneq (${PWD},${CURDIR})
+-override RELOCATE_BUILD := 1
+-# If we're run from the build dir, don't let it get cleaned up later.
+-ifeq (${PWD}/,${OUT})
+-$(shell touch "$(PWD)/.dont_delete_on_clean")
+-endif
+-endif  # ifneq (${PWD},${CURDIR}
+-
+-# "Relocate" if we need to restart without implicit rules.
+-ifeq ($(subst r,,$(MAKEFLAGS)),$(MAKEFLAGS))
+-override RELOCATE_BUILD := 1
+-endif
+-
+-ifeq (${RELOCATE_BUILD},1)
+-# By default, silence build output. Reused below as well.
+-QUIET = @
+-ifeq ($(VERBOSE),1)
+-  QUIET=
+-endif
+-
+-# This target will override all targets, including prerequisites. To avoid
+-# calling $(MAKE) once per prereq on the given CMDGOAL, we guard it with a local
+-# variable.
+-RUN_ONCE := 0
+-MAKECMDGOALS ?= all
+-# Keep the rules split as newer make does not allow them to be declared
+-# on the same line.  But the way :: rules work, the _all here will also
+-# invoke the %:: rule while retaining "_all" as the default.
+-_all::
+-%::
+-	$(if $(filter 0,$(RUN_ONCE)), \
+-	  cd "$(OUT)" && \
+-	  $(MAKE) -r -I "$(SRC)" -f "$(CURDIR)/Makefile" \
+-	    SRC="$(CURDIR)" OUT="$(OUT)" $(foreach g,$(MAKECMDGOALS),"$(g)"),)
+-	$(eval RUN_ONCE := 1)
+-pass-to-subcall := 1
+-endif
+-
+-ifeq ($(pass-to-subcall),)
+-
+-# Only call MODULE if we're in a submodule
+-MODULES_LIST := $(filter-out Makefile %.d,$(MAKEFILE_LIST))
+-ifeq ($(words $(filter-out Makefile common.mk %.d $(SRC)/Makefile \
+-                           $(SRC)/common.mk,$(MAKEFILE_LIST))),0)
+-
+-# All the top-level defines outside of module.mk.
+-
+-#
+-# Helper macros
+-#
+-
+-# Create the directory if it doesn't yet exist.
+-define auto_mkdir
+-  $(if $(wildcard $(dir $1)),$2,$(QUIET)mkdir -p "$(dir $1)")
+-endef
+-
+-# Creates the actual archive with an index.
+-# The target $@ must end with .pic.a or .pie.a.
+-define update_archive
+-  $(call auto_mkdir,$(TARGET_OR_MEMBER))
+-  $(QUIET)# Create the archive in one step to avoid parallel use accessing it
+-  $(QUIET)# before all the symbols are present.
+-  @$(ECHO) "AR		$(subst \
+-$(SRC)/,,$(^:.o=$(suffix $(basename $(TARGET_OR_MEMBER))).o)) \
+--> $(subst $(SRC)/,,$(TARGET_OR_MEMBER))"
+-  $(QUIET)$(AR) rcs $(TARGET_OR_MEMBER) \
+-          $(subst $(SRC)/,,$(^:.o=$(suffix $(basename $(TARGET_OR_MEMBER))).o))
+-endef
+-
+-# Default compile from objects using pre-requisites but filters out
+-# subdirs and .d files.
+-define cc_binary
+-  $(call COMPILE_BINARY_implementation,CC,$(CFLAGS) $(1),$(EXTRA_FLAGS))
+-endef
+-
+-define cxx_binary
+-  $(call COMPILE_BINARY_implementation,CXX,$(CXXFLAGS) $(1),$(EXTRA_FLAGS))
+-endef
+-
+-# Default compile from objects using pre-requisites but filters out
+-# subdirs and .d files.
+-define cc_library
+-  $(call COMPILE_LIBRARY_implementation,CC,$(CFLAGS) $(1),$(EXTRA_FLAGS))
+-endef
+-define cxx_library
+-  $(call COMPILE_LIBRARY_implementation,CXX,$(CXXFLAGS) $(1),$(EXTRA_FLAGS))
+-endef
+-
+-# Deletes files silently if they exist. Meant for use in any local
+-# clean targets.
+-define silent_rm
+-  $(if $(wildcard $(1)),
+-  $(QUIET)($(ECHO) -n '$(COLOR_RED)CLEANFILE$(COLOR_RESET)		' && \
+-    $(ECHO) '$(subst $(OUT)/,,$(wildcard $(1)))' && \
+-    $(RM) $(1) 2>/dev/null) || true,)
+-endef
+-define silent_rmdir
+-  $(if $(wildcard $(1)),
+-    $(if $(wildcard $(1)/*),
+-  $(QUIET)# $(1) not empty [$(wildcard $(1)/*)]. Not deleting.,
+-  $(QUIET)($(ECHO) -n '$(COLOR_RED)CLEANDIR$(COLOR_RESET)		' && \
+-    $(ECHO) '$(subst $(OUT)/,,$(wildcard $(1)))' && \
+-    $(RMDIR) $(1) 2>/dev/null) || true),)
+-endef
+-
+-#
+-# Default variable values
+-#
+-
+-# Only override toolchain vars if they are from make.
+-CROSS_COMPILE ?=
+-define override_var
+-ifneq ($(filter undefined default,$(origin $1)),)
+-$1 = $(CROSS_COMPILE)$2
+-endif
+-endef
+-$(eval $(call override_var,AR,ar))
+-$(eval $(call override_var,CC,gcc))
+-$(eval $(call override_var,CXX,g++))
+-$(eval $(call override_var,OBJCOPY,objcopy))
+-$(eval $(call override_var,PKG_CONFIG,pkg-config))
+-$(eval $(call override_var,RANLIB,ranlib))
+-$(eval $(call override_var,STRIP,strip))
+-
+-RMDIR ?= rmdir
+-ECHO = /bin/echo -e
+-
+-ifeq ($(lastword $(subst /, ,$(CC))),clang)
+-CDRIVER = clang
+-else
+-CDRIVER = gcc
+-endif
+-
+-ifeq ($(lastword $(subst /, ,$(CXX))),clang++)
+-CXXDRIVER = clang
+-else
+-CXXDRIVER = gcc
+-endif
+-
+-# Internal macro to support check_XXX macros below.
+-# Usage: $(call check_compile, [code], [compiler], [code_type], [c_flags],
+-#               [extra_c_flags], [library_flags], [success_ret], [fail_ret])
+-# Return: [success_ret] if compile succeeded, otherwise [fail_ret]
+-check_compile = $(shell printf '%b\n' $(1) | \
+-  $($(2)) $($(4)) -x $(3) $(LDFLAGS) $(5) - $(6) -o /dev/null > /dev/null 2>&1 \
+-  && echo "$(7)" || echo "$(8)")
+-
+-# Helper macro to check whether a test program will compile with the specified
+-# compiler flags.
+-# Usage: $(call check_compile_cc, [code], [flags], [alternate_flags])
+-# Return: [flags] if compile succeeded, otherwise [alternate_flags]
+-check_compile_cc = $(call check_compile,$(1),CC,c,CFLAGS,$(2),,$(2),$(3))
+-check_compile_cxx = $(call check_compile,$(1),CXX,c++,CXXFLAGS,$(2),,$(2),$(3))
+-
+-# Helper macro to check whether a test program will compile with the specified
+-# libraries.
+-# Usage: $(call check_compile_cc, [code], [library_flags], [alternate_flags])
+-# Return: [library_flags] if compile succeeded, otherwise [alternate_flags]
+-check_libs_cc = $(call check_compile,$(1),CC,c,CFLAGS,,$(2),$(2),$(3))
+-check_libs_cxx = $(call check_compile,$(1),CXX,c++,CXXFLAGS,,$(2),$(2),$(3))
+-
+-# Helper macro to check whether the compiler accepts the specified flags.
+-# Usage: $(call check_compile_cc, [flags], [alternate_flags])
+-# Return: [flags] if compile succeeded, otherwise [alternate_flags]
+-check_cc = $(call check_compile_cc,'int main() { return 0; }',$(1),$(2))
+-check_cxx = $(call check_compile_cxx,'int main() { return 0; }',$(1),$(2))
+-
+-# Choose the stack protector flags based on whats supported by the compiler.
+-SSP_CFLAGS := $(call check_cc,-fstack-protector-strong)
+-ifeq ($(SSP_CFLAGS),)
+- SSP_CFLAGS := $(call check_cc,-fstack-protector-all)
+-endif
+-
+-# To update these from an including Makefile:
+-#  CXXFLAGS += -mahflag  # Append to the list
+-#  CXXFLAGS := -mahflag $(CXXFLAGS) # Prepend to the list
+-#  CXXFLAGS := $(filter-out badflag,$(CXXFLAGS)) # Filter out a value
+-# The same goes for CFLAGS.
+-COMMON_CFLAGS-gcc := -fvisibility=internal -ggdb3 -Wa,--noexecstack
+-COMMON_CFLAGS-clang := -fvisibility=hidden -ggdb
+-COMMON_CFLAGS := -Wall -Werror -fno-strict-aliasing $(SSP_CFLAGS) -O1 -Wformat=2
+-CXXFLAGS += $(COMMON_CFLAGS) $(COMMON_CFLAGS-$(CXXDRIVER))
+-CFLAGS += $(COMMON_CFLAGS) $(COMMON_CFLAGS-$(CDRIVER))
+-CPPFLAGS += -D_FORTIFY_SOURCE=2
+-
+-# Enable large file support.
+-CPPFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
+-
+-# Disable exceptions based on the CXXEXCEPTIONS setting.
+-ifeq ($(CXXEXCEPTIONS),0)
+-  CXXFLAGS := $(CXXFLAGS) -fno-exceptions -fno-unwind-tables \
+-    -fno-asynchronous-unwind-tables
+-endif
+-
+-ifeq ($(MODE),opt)
+-  # Up the optimizations.
+-  CFLAGS := $(filter-out -O1,$(CFLAGS)) -O2
+-  CXXFLAGS := $(filter-out -O1,$(CXXFLAGS)) -O2
+-  # Only drop -g* if symbols aren't desired.
+-  ifeq ($(NOSTRIP),0)
+-    # TODO: do we want -fomit-frame-pointer on x86?
+-    CFLAGS := $(filter-out -ggdb3,$(CFLAGS))
+-    CXXFLAGS := $(filter-out -ggdb3,$(CXXFLAGS))
+-  endif
+-endif
+-
+-ifeq ($(MODE),profiling)
+-  CFLAGS := $(CFLAGS) -O0 -g  --coverage
+-  CXXFLAGS := $(CXXFLAGS) -O0 -g  --coverage
+-  LDFLAGS := $(LDFLAGS) --coverage
+-endif
+-
+-LDFLAGS := $(LDFLAGS) -Wl,-z,relro -Wl,-z,noexecstack -Wl,-z,now
+-
+-# Fancy helpers for color if a prompt is defined
+-ifeq ($(COLOR),1)
+-COLOR_RESET = \x1b[0m
+-COLOR_GREEN = \x1b[32;01m
+-COLOR_RED = \x1b[31;01m
+-COLOR_YELLOW = \x1b[33;01m
+-endif
+-
+-# By default, silence build output.
+-QUIET = @
+-ifeq ($(VERBOSE),1)
+-  QUIET=
+-endif
+-
+-#
+-# Implementation macros for compile helpers above
+-#
+-
+-# Useful for dealing with pie-broken toolchains.
+-# Call make with PIE=0 to disable default PIE use.
+-OBJ_PIE_FLAG = -fPIE
+-COMPILE_PIE_FLAG = -pie
+-ifeq ($(PIE),0)
+-  OBJ_PIE_FLAG =
+-  COMPILE_PIE_FLAG =
+-endif
+-
+-# Favor member targets first for CXX_BINARY(%) magic.
+-# And strip out nested members if possible.
+-LP := (
+-RP := )
+-TARGET_OR_MEMBER = $(lastword $(subst $(LP), ,$(subst $(RP),,$(or $%,$@))))
+-
+-# Default compile from objects using pre-requisites but filters out
+-# all non-.o files.
+-define COMPILE_BINARY_implementation
+-  @$(ECHO) "LD$(1)		$(subst $(PWD)/,,$(TARGET_OR_MEMBER))"
+-  $(call auto_mkdir,$(TARGET_OR_MEMBER))
+-  $(QUIET)$($(1)) $(COMPILE_PIE_FLAGS) -o $(TARGET_OR_MEMBER) \
+-    $(2) $(LDFLAGS) \
+-    $(filter %.o %.a,$(^:.o=.pie.o)) \
+-    $(foreach so,$(filter %.so,$^),-L$(dir $(so)) \
+-                            -l$(patsubst lib%,%,$(basename $(notdir $(so))))) \
+-    $(LDLIBS)
+-  $(call conditional_strip)
+-  @$(ECHO) -n "BIN		"
+-  @$(ECHO) "$(COLOR_GREEN)$(subst $(PWD)/,,$(TARGET_OR_MEMBER))$(COLOR_RESET)"
+-  @$(ECHO) "	$(COLOR_YELLOW)-----$(COLOR_RESET)"
+-endef
+-
+-# TODO: add version support extracted from PV environment variable
+-#ifeq ($(PV),9999)
+-#$(warning PV=$(PV). If shared object versions matter, please force PV=.)
+-#endif
+-# Then add -Wl,-soname,$@.$(PV) ?
+-
+-# Default compile from objects using pre-requisites but filters out
+-# all non-.o values. (Remember to add -L$(OUT) -llib)
+-COMMA := ,
+-define COMPILE_LIBRARY_implementation
+-  @$(ECHO) "SHARED$(1)	$(subst $(PWD)/,,$(TARGET_OR_MEMBER))"
+-  $(call auto_mkdir,$(TARGET_OR_MEMBER))
+-  $(QUIET)$($(1)) -shared -Wl,-E -o $(TARGET_OR_MEMBER) \
+-    $(2) $(LDFLAGS) \
+-    $(if $(filter %.a,$^),-Wl$(COMMA)--whole-archive,) \
+-    $(filter %.o ,$(^:.o=.pic.o)) \
+-    $(foreach a,$(filter %.a,$^),-L$(dir $(a)) \
+-                            -l$(patsubst lib%,%,$(basename $(notdir $(a))))) \
+-    $(foreach so,$(filter %.so,$^),-L$(dir $(so)) \
+-                            -l$(patsubst lib%,%,$(basename $(notdir $(so))))) \
+-    $(LDLIBS)
+-  $(call conditional_strip)
+-  @$(ECHO) -n "LIB		$(COLOR_GREEN)"
+-  @$(ECHO) "$(subst $(PWD)/,,$(TARGET_OR_MEMBER))$(COLOR_RESET)"
+-  @$(ECHO) "	$(COLOR_YELLOW)-----$(COLOR_RESET)"
+-endef
+-
+-define conditional_strip
+-  $(if $(filter 0,$(NOSTRIP)),$(call strip_artifact))
+-endef
+-
+-define strip_artifact
+-  @$(ECHO) "STRIP		$(subst $(OUT)/,,$(TARGET_OR_MEMBER))"
+-  $(if $(filter 1,$(SPLITDEBUG)), @$(ECHO) -n "DEBUG	"; \
+-    $(ECHO) "$(COLOR_YELLOW)\
+-$(subst $(OUT)/,,$(TARGET_OR_MEMBER)).debug$(COLOR_RESET)")
+-  $(if $(filter 1,$(SPLITDEBUG)), \
+-    $(QUIET)$(OBJCOPY) --only-keep-debug "$(TARGET_OR_MEMBER)" \
+-      "$(TARGET_OR_MEMBER).debug")
+-  $(if $(filter-out dbg,$(MODE)),$(QUIET)$(STRIP) --strip-unneeded \
+-    "$(TARGET_OR_MEMBER)",)
+-endef
+-
+-#
+-# Global pattern rules
+-#
+-
+-# Below, the archive member syntax is abused to create fancier
+-# syntactic sugar for recipe authors that avoids needed to know
+-# subcall options.  The downside is that make attempts to look
+-# into the phony archives for timestamps. This will cause the final
+-# target to be rebuilt/linked on _every_ call to make even when nothing
+-# has changed.  Until a better way presents itself, we have helpers that
+-# do the stat check on make's behalf.  Dodgy but simple.
+-define old_or_no_timestamp
+-  $(if $(realpath $%),,$(1))
+-  $(if $(shell find $^ -cnewer "$%" 2>/dev/null),$(1))
+-endef
+-
+-define check_deps
+-  $(if $(filter 0,$(words $^)),\
+-    $(error Missing dependencies or declaration of $@($%)),)
+-endef
+-
+-# Build a cxx target magically
+-CXX_BINARY(%):
+-	$(call check_deps)
+-	$(call old_or_no_timestamp,$(call cxx_binary))
+-clean: CLEAN(CXX_BINARY*)
+-
+-CC_BINARY(%):
+-	$(call check_deps)
+-	$(call old_or_no_timestamp,$(call cc_binary))
+-clean: CLEAN(CC_BINARY*)
+-
+-CXX_STATIC_BINARY(%):
+-	$(call check_deps)
+-	$(call old_or_no_timestamp,$(call cxx_binary,-static))
+-clean: CLEAN(CXX_STATIC_BINARY*)
+-
+-CC_STATIC_BINARY(%):
+-	$(call check_deps)
+-	$(call old_or_no_timestamp,$(call cc_binary,-static))
+-clean: CLEAN(CC_STATIC_BINARY*)
+-
+-CXX_LIBRARY(%):
+-	$(call check_deps)
+-	$(call old_or_no_timestamp,$(call cxx_library))
+-clean: CLEAN(CXX_LIBRARY*)
+-
+-CXX_LIBARY(%):
+-	$(error Typo alert! LIBARY != LIBRARY)
+-
+-CC_LIBRARY(%):
+-	$(call check_deps)
+-	$(call old_or_no_timestamp,$(call cc_library))
+-clean: CLEAN(CC_LIBRARY*)
+-
+-CC_LIBARY(%):
+-	$(error Typo alert! LIBARY != LIBRARY)
+-
+-CXX_STATIC_LIBRARY(%):
+-	$(call check_deps)
+-	$(call old_or_no_timestamp,$(call update_archive))
+-clean: CLEAN(CXX_STATIC_LIBRARY*)
+-
+-CXX_STATIC_LIBARY(%):
+-	$(error Typo alert! LIBARY != LIBRARY)
+-
+-CC_STATIC_LIBRARY(%):
+-	$(call check_deps)
+-	$(call old_or_no_timestamp,$(call update_archive))
+-clean: CLEAN(CC_STATIC_LIBRARY*)
+-
+-CC_STATIC_LIBARY(%):
+-	$(error Typo alert! LIBARY != LIBRARY)
+-
+-
+-TEST(%): % qemu_chroot_install
+-	$(call TEST_implementation)
+-.PHONY: TEST
+-
+-# multiple targets with a wildcard need to share an directory.
+-# Don't use this directly it just makes sure the directory is removed _after_
+-# the files are.
+-CLEANFILE(%):
+-	$(call silent_rm,$(TARGET_OR_MEMBER))
+-.PHONY: CLEANFILE
+-
+-CLEAN(%): CLEANFILE(%)
+-	$(QUIET)# CLEAN($%) meta-target called
+-	$(if $(filter-out $(PWD)/,$(dir $(abspath $(TARGET_OR_MEMBER)))), \
+-	  $(call silent_rmdir,$(dir $(abspath $(TARGET_OR_MEMBER)))),\
+-	  $(QUIET)# Not deleting $(dir $(abspath $(TARGET_OR_MEMBER))) yet.)
+-.PHONY: CLEAN
+-
+-#
+-# Top-level objects and pattern rules
+-#
+-
+-# All objects for .c files at the top level
+-C_OBJECTS = $(patsubst $(SRC)/%.c,%.o,$(wildcard $(SRC)/*.c))
+-
+-
+-# All objects for .cxx files at the top level
+-CXX_OBJECTS = $(patsubst $(SRC)/%.cc,%.o,$(wildcard $(SRC)/*.cc))
+-
+-# Note, the catch-all pattern rules don't work in subdirectories because
+-# we're building from the $(OUT) directory. At the top-level (here) they will
+-# work, but we go ahead and match using the module form.  Then we can place a
+-# generic pattern rule to capture leakage from the main Makefile. (Later in the
+-# file.)
+-#
+-# The reason target specific pattern rules work well for modules,
+-# MODULE_C_OBJECTS, is because it scopes the behavior to the given target which
+-# ensures we get a relative directory offset from $(OUT) which otherwise would
+-# not match without further magic on a per-subdirectory basis.
+-
+-# Creates object file rules. Call with eval.
+-# $(1) list of .o files
+-# $(2) source type (CC or CXX)
+-# $(3) source suffix (cc or c)
+-# $(4) compiler flag name (CFLAGS or CXXFLAGS)
+-# $(5) source dir: _only_ if $(SRC). Leave blank for obj tree.
+-define add_object_rules
+-$(patsubst %.o,%.pie.o,$(1)): %.pie.o: $(5)%.$(3) %.o.depends
+-	$$(call auto_mkdir,$$@)
+-	$$(call OBJECT_PATTERN_implementation,$(2),\
+-          $$(basename $$@),$$($(4)) $$(CPPFLAGS) $$(OBJ_PIE_FLAG))
+-
+-$(patsubst %.o,%.pic.o,$(1)): %.pic.o: $(5)%.$(3) %.o.depends
+-	$$(call auto_mkdir,$$@)
+-	$$(call OBJECT_PATTERN_implementation,$(2),\
+-          $$(basename $$@),$$($(4)) $$(CPPFLAGS) -fPIC)
+-
+-# Placeholder for depends
+-$(patsubst %.o,%.o.depends,$(1)):
+-	$$(call auto_mkdir,$$@)
+-	$$(QUIET)touch "$$@"
+-
+-$(1): %.o: %.pic.o %.pie.o
+-	$$(call auto_mkdir,$$@)
+-	$$(QUIET)touch "$$@"
+-endef
+-
+-define OBJECT_PATTERN_implementation
+-  @$(ECHO) "$(1)		$(subst $(SRC)/,,$<) -> $(2).o"
+-  $(call auto_mkdir,$@)
+-  $(QUIET)$($(1)) -c -MD -MF $(2).d $(3) -o $(2).o $<
+-  $(QUIET)# Wrap all the deps in $$(wildcard) so a missing header
+-  $(QUIET)# won't cause weirdness.  First we remove newlines and \,
+-  $(QUIET)# then wrap it.
+-  $(QUIET)sed -i -e :j -e '$$!N;s|\\\s*\n| |;tj' \
+-    -e 's|^\(.*\s*:\s*\)\(.*\)$$|\1 $$\(wildcard \2\)|' $(2).d
+-endef
+-
+-# Now actually register handlers for C(XX)_OBJECTS.
+-$(eval $(call add_object_rules,$(C_OBJECTS),CC,c,CFLAGS,$(SRC)/))
+-$(eval $(call add_object_rules,$(CXX_OBJECTS),CXX,cc,CXXFLAGS,$(SRC)/))
+-
+-# Disable default pattern rules to help avoid leakage.
+-# These may already be handled by '-r', but let's keep it to be safe.
+-%: %.o ;
+-%.a: %.o ;
+-%.o: %.c ;
+-%.o: %.cc ;
+-
+-# NOTE: A specific rule for archive objects is avoided because parallel
+-#       update of the archive causes build flakiness.
+-# Instead, just make the objects the prerequisites and use update_archive
+-# To use the foo.a(obj.o) functionality, targets would need to specify the
+-# explicit object they expect on the prerequisite line.
+-
+-#
+-# Architecture detection and QEMU wrapping
+-#
+-
+-HOST_ARCH ?= $(shell uname -m)
+-override ARCH := $(strip $(ARCH))
+-override HOST_ARCH := $(strip $(HOST_ARCH))
+-# emake will supply "x86" or "arm" for ARCH, but
+-# if uname -m runs and you get x86_64, then this subst
+-# will break.
+-ifeq ($(subst x86,i386,$(ARCH)),i386)
+-  QEMU_ARCH := $(subst x86,i386,$(ARCH))  # x86 -> i386
+-else ifeq ($(subst amd64,x86_64,$(ARCH)),x86_64)
+-  QEMU_ARCH := $(subst amd64,x86_64,$(ARCH))  # amd64 -> x86_64
+-else
+-  QEMU_ARCH = $(ARCH)
+-endif
+-override QEMU_ARCH := $(strip $(QEMU_ARCH))
+-
+-# If we're cross-compiling, try to use qemu for running the tests.
+-ifneq ($(QEMU_ARCH),$(HOST_ARCH))
+-  ifeq ($(SYSROOT),)
+-    $(info SYSROOT not defined. qemu-based testing disabled)
+-  else
+-    # A SYSROOT is assumed for QEmu use.
+-    USE_QEMU ?= 1
+-
+-    # Allow 64-bit hosts to run 32-bit without qemu.
+-    ifeq ($(HOST_ARCH),x86_64)
+-      ifeq ($(QEMU_ARCH),i386)
+-        USE_QEMU = 0
+-      endif
+-    endif
+-  endif
+-else
+-  USE_QEMU ?= 0
+-endif
+-
+-# Normally we don't need to run as root or do bind mounts, so only
+-# enable it by default when we're using QEMU.
+-NEEDS_ROOT ?= $(USE_QEMU)
+-NEEDS_MOUNTS ?= $(USE_QEMU)
+-
+-SYSROOT_OUT = $(OUT)
+-ifneq ($(SYSROOT),)
+-  SYSROOT_OUT = $(subst $(SYSROOT),,$(OUT))
+-else
+-  # Default to / when all the empty-sysroot logic is done.
+-  SYSROOT = /
+-endif
+-
+-QEMU_NAME = qemu-$(QEMU_ARCH)
+-QEMU_PATH = /build/bin/$(QEMU_NAME)
+-QEMU_SYSROOT_PATH = $(SYSROOT)$(QEMU_PATH)
+-QEMU_SRC_PATH = /usr/bin/$(QEMU_NAME)
+-QEMU_BINFMT_PATH = /proc/sys/fs/binfmt_misc/$(QEMU_NAME)
+-QEMU_REGISTER_PATH = /proc/sys/fs/binfmt_misc/register
+-
+-QEMU_MAGIC_arm = ":$(QEMU_NAME):M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/build/bin/qemu-arm:"
+-
+-
+-#
+-# Output full configuration at top level
+-#
+-
+-# Don't show on clean
+-ifneq ($(MAKECMDGOALS),clean)
+-  $(info build configuration:)
+-  $(info - OUT=$(OUT))
+-  $(info - SRC=$(SRC))
+-  $(info - MODE=$(MODE))
+-  $(info - SPLITDEBUG=$(SPLITDEBUG))
+-  $(info - NOSTRIP=$(NOSTRIP))
+-  $(info - VALGRIND=$(VALGRIND))
+-  $(info - COLOR=$(COLOR))
+-  $(info - CXXEXCEPTIONS=$(CXXEXCEPTIONS))
+-  $(info - ARCH=$(ARCH))
+-  $(info - QEMU_ARCH=$(QEMU_ARCH))
+-  $(info - USE_QEMU=$(USE_QEMU))
+-  $(info - NEEDS_ROOT=$(NEEDS_ROOT))
+-  $(info - NEEDS_MOUNTS=$(NEEDS_MOUNTS))
+-  $(info - SYSROOT=$(SYSROOT))
+-  $(info )
+-endif
+-
+-#
+-# Standard targets with detection for when they are improperly configured.
+-#
+-
+-# all does not include tests by default
+-all:
+-	$(QUIET)(test -z "$^" && \
+-	$(ECHO) "You must add your targets as 'all' prerequisites") || true
+-	$(QUIET)test -n "$^"
+-
+-# Builds and runs tests for the target arch
+-# Run them in parallel
+-# After the test have completed, if profiling, run coverage analysis
+-tests:
+-ifeq ($(MODE),profiling)
+-	@$(ECHO) "COVERAGE [$(COLOR_YELLOW)STARTED$(COLOR_RESET)]"
+-	$(QUIET)FILES="";						\
+-		for GCNO in `find . -name "*.gcno"`; do			\
+-			GCDA="$${GCNO%.gcno}.gcda";			\
+-			if [ -e $${GCDA} ]; then			\
+-				FILES="$${FILES} $${GCDA}";		\
+-			fi						\
+-		done;							\
+-		if [ -n "$${FILES}" ]; then				\
+-			gcov -l $${FILES};				\
+-			lcov --capture --directory .			\
+-				--output-file=lcov-coverage.info;	\
+-			genhtml lcov-coverage.info			\
+-				--output-directory lcov-html;		\
+-		fi
+-	@$(ECHO) "COVERAGE [$(COLOR_YELLOW)FINISHED$(COLOR_RESET)]"
+-endif
+-.PHONY: tests
+-
+-qemu_chroot_install:
+-ifeq ($(USE_QEMU),1)
+-	$(QUIET)$(ECHO) "QEMU   Preparing $(QEMU_NAME)"
+-	@# Copying strategy
+-	@# Compare /usr/bin/qemu inode to /build/$board/build/bin/qemu, if different
+-	@# hard link to a temporary file, then rename temp to target. This should
+-	@# ensure that once $QEMU_SYSROOT_PATH exists it will always exist, regardless
+-	@# of simultaneous test setups.
+-	$(QUIET)if [[ ! -e $(QEMU_SYSROOT_PATH) || \
+-	    `stat -c %i $(QEMU_SRC_PATH)` != `stat -c %i $(QEMU_SYSROOT_PATH)` \
+-	    ]]; then \
+-	  $(ROOT_CMD) ln -Tf $(QEMU_SRC_PATH) $(QEMU_SYSROOT_PATH).$$$$; \
+-	  $(ROOT_CMD) mv -Tf $(QEMU_SYSROOT_PATH).$$$$ $(QEMU_SYSROOT_PATH); \
+-	fi
+-
+-	@# Prep the binfmt handler. First mount if needed, then unregister any bad
+-	@# mappings and then register our mapping.
+-	@# There may still be some race conditions here where one script de-registers
+-	@# and another script starts executing before it gets re-registered, however
+-	@# it should be rare.
+-	-$(QUIET)[[ -e $(QEMU_REGISTER_PATH) ]] || \
+-	  $(ROOT_CMD) mount binfmt_misc -t binfmt_misc \
+-	    /proc/sys/fs/binfmt_misc
+-
+-	-$(QUIET)if [[ -e $(QEMU_BINFMT_PATH) && \
+-	      `awk '$$1 == "interpreter" {print $$NF}' $(QEMU_BINFMT_PATH)` != \
+-	      "$(QEMU_PATH)" ]]; then \
+-	  echo -1 | $(ROOT_CMD) tee $(QEMU_BINFMT_PATH) >/dev/null; \
+-	fi
+-
+-	-$(if $(QEMU_MAGIC_$(ARCH)),$(QUIET)[[ -e $(QEMU_BINFMT_PATH) ]] || \
+-	  echo $(QEMU_MAGIC_$(ARCH)) | $(ROOT_CMD) tee $(QEMU_REGISTER_PATH) \
+-	    >/dev/null)
+-endif
+-.PHONY: qemu_clean qemu_chroot_install
+-
+-# TODO(wad) Move to -L $(SYSROOT) and fakechroot when qemu-user
+-#           doesn't hang traversing /proc from SYSROOT.
+-SUDO_CMD = sudo
+-UNSHARE_CMD = unshare
+-QEMU_CMD =
+-ROOT_CMD = $(if $(filter 1,$(NEEDS_ROOT)),$(SUDO_CMD) , )
+-MOUNT_CMD = $(if $(filter 1,$(NEEDS_MOUNTS)),$(ROOT_CMD) mount, \#)
+-UMOUNT_CMD = $(if $(filter 1,$(NEEDS_MOUNTS)),$(ROOT_CMD) umount, \#)
+-QEMU_LDPATH = $(SYSROOT_LDPATH):/lib64:/lib:/usr/lib64:/usr/lib
+-ROOT_CMD_LDPATH = $(SYSROOT_LDPATH):$(SYSROOT)/lib64:
+-ROOT_CMD_LDPATH := $(ROOT_CMD_LDPATH):$(SYSROOT)/lib:$(SYSROOT)/usr/lib64:
+-ROOT_CMD_LDPATH := $(ROOT_CMD_LDPATH):$(SYSROOT)/usr/lib
+-ifeq ($(USE_QEMU),1)
+-  export QEMU_CMD = \
+-   $(SUDO_CMD) chroot $(SYSROOT) $(QEMU_PATH) \
+-   -drop-ld-preload \
+-   -E LD_LIBRARY_PATH="$(QEMU_LDPATH):$(patsubst $(OUT),,$(LD_DIRS))" \
+-   -E HOME="$(HOME)" -E SRC="$(SRC)" --
+-  # USE_QEMU conditional function
+-  define if_qemu
+-    $(1)
+-  endef
+-else
+-  ROOT_CMD = $(if $(filter 1,$(NEEDS_ROOT)),sudo, ) \
+-    LD_LIBRARY_PATH="$(ROOT_CMD_LDPATH):$(LD_DIRS)"
+-  define if_qemu
+-    $(2)
+-  endef
+-endif
+-
+-VALGRIND_CMD =
+-ifeq ($(VALGRIND),1)
+-  VALGRIND_CMD = /usr/bin/valgrind --tool=memcheck $(VALGRIND_ARGS) --
+-endif
+-
+-define TEST_implementation
+-  $(QUIET)$(call TEST_setup)
+-  $(QUIET)$(call TEST_run)
+-  $(QUIET)$(call TEST_teardown)
+-  $(QUIET)exit $$(cat $(OUT)$(TARGET_OR_MEMBER).status.test)
+-endef
+-
+-define TEST_setup
+-  @$(ECHO) -n "TEST		$(TARGET_OR_MEMBER) "
+-  @$(ECHO) "[$(COLOR_YELLOW)SETUP$(COLOR_RESET)]"
+-  $(QUIET)# Setup a target-specific results file
+-  $(QUIET)(echo > $(OUT)$(TARGET_OR_MEMBER).setup.test)
+-  $(QUIET)(echo 1 > $(OUT)$(TARGET_OR_MEMBER).status.test)
+-  $(QUIET)(echo > $(OUT)$(TARGET_OR_MEMBER).cleanup.test)
+-  $(QUIET)# No setup if we are not using QEMU
+-  $(QUIET)# TODO(wad) this is racy until we use a vfs namespace
+-  $(call if_qemu,\
+-    $(QUIET)(echo "mkdir -p '$(SYSROOT)/proc' '$(SYSROOT)/dev' \
+-                            '$(SYSROOT)/mnt/host/source'" \
+-             >> "$(OUT)$(TARGET_OR_MEMBER).setup.test"))
+-  $(call if_qemu,\
+-    $(QUIET)(echo "$(MOUNT_CMD) --bind /mnt/host/source \
+-             '$(SYSROOT)/mnt/host/source'" \
+-             >> "$(OUT)$(TARGET_OR_MEMBER).setup.test"))
+-  $(call if_qemu,\
+-    $(QUIET)(echo "$(MOUNT_CMD) --bind /proc '$(SYSROOT)/proc'" \
+-             >> "$(OUT)$(TARGET_OR_MEMBER).setup.test"))
+-  $(call if_qemu,\
+-    $(QUIET)(echo "$(MOUNT_CMD) --bind /dev '$(SYSROOT)/dev'" \
+-             >> "$(OUT)$(TARGET_OR_MEMBER).setup.test"))
+-endef
+-
+-define TEST_teardown
+-  @$(ECHO) -n "TEST		$(TARGET_OR_MEMBER) "
+-  @$(ECHO) "[$(COLOR_YELLOW)TEARDOWN$(COLOR_RESET)]"
+-  $(call if_qemu, $(QUIET)$(SHELL) "$(OUT)$(TARGET_OR_MEMBER).cleanup.test")
+-endef
+-
+-# Use GTEST_ARGS.[arch] if defined.
+-override GTEST_ARGS.real = \
+- $(call if_qemu,$(GTEST_ARGS.qemu.$(QEMU_ARCH)),$(GTEST_ARGS.host.$(HOST_ARCH)))
+-
+-define TEST_run
+-  @$(ECHO) -n "TEST		$(TARGET_OR_MEMBER) "
+-  @$(ECHO) "[$(COLOR_GREEN)RUN$(COLOR_RESET)]"
+-  $(QUIET)(echo 1 > "$(OUT)$(TARGET_OR_MEMBER).status.test")
+-  $(QUIET)(echo $(ROOT_CMD) SRC="$(SRC)" $(QEMU_CMD) $(VALGRIND_CMD) \
+-    "$(strip $(call if_qemu, $(SYSROOT_OUT),$(OUT))$(TARGET_OR_MEMBER))" \
+-      $(if $(filter-out 0,$(words $(GTEST_ARGS.real))),$(GTEST_ARGS.real),\
+-           $(GTEST_ARGS)) >> "$(OUT)$(TARGET_OR_MEMBER).setup.test")
+-  -$(QUIET)$(call if_qemu,$(SUDO_CMD) $(UNSHARE_CMD) -m) $(SHELL) \
+-      $(OUT)$(TARGET_OR_MEMBER).setup.test \
+-  && echo 0 > "$(OUT)$(TARGET_OR_MEMBER).status.test"
+-endef
+-
+-# Recursive list reversal so that we get RMDIR_ON_CLEAN in reverse order.
+-define reverse
+-$(if $(1),$(call reverse,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1))
+-endef
+-
+-clean: qemu_clean
+-clean: CLEAN($(OUT)*.d) CLEAN($(OUT)*.o) CLEAN($(OUT)*.debug)
+-clean: CLEAN($(OUT)*.test) CLEAN($(OUT)*.depends)
+-clean: CLEAN($(OUT)*.gcno) CLEAN($(OUT)*.gcda) CLEAN($(OUT)*.gcov)
+-clean: CLEAN($(OUT)lcov-coverage.info) CLEAN($(OUT)lcov-html)
+-
+-clean:
+-	$(QUIET)# Always delete the containing directory last.
+-	$(call silent_rmdir,$(OUT))
+-
+-FORCE: ;
+-# Empty rule for use when no special targets are needed, like large_tests
+-NONE:
+-
+-.PHONY: clean NONE valgrind NONE
+-.DEFAULT_GOAL  :=  all
+-# Don't let make blow away "intermediates"
+-.PRECIOUS: %.pic.o %.pie.o %.a %.pic.a %.pie.a %.test
+-
+-# Start accruing build info
+-OUT_DIRS = $(OUT)
+-LD_DIRS = $(OUT)
+-SRC_DIRS = $(SRC)
+-
+-include $(wildcard $(OUT)*.d)
+-SUBMODULE_DIRS = $(wildcard $(SRC)/*/module.mk)
+-include $(SUBMODULE_DIRS)
+-
+-
+-else  ## In duplicate inclusions of common.mk
+-
+-# Get the current inclusion directory without a trailing slash
+-MODULE := $(patsubst %/,%, \
+-           $(dir $(lastword $(filter-out %common.mk,$(MAKEFILE_LIST)))))
+-MODULE := $(subst $(SRC)/,,$(MODULE))
+-MODULE_NAME := $(subst /,_,$(MODULE))
+-#VPATH := $(MODULE):$(VPATH)
+-
+-
+-# Depth first
+-$(eval OUT_DIRS += $(OUT)$(MODULE))
+-$(eval SRC_DIRS += $(OUT)$(MODULE))
+-$(eval LD_DIRS := $(LD_DIRS):$(OUT)$(MODULE))
+-
+-# Add the defaults from this dir to rm_clean
+-clean: CLEAN($(OUT)$(MODULE)/*.d) CLEAN($(OUT)$(MODULE)/*.o)
+-clean: CLEAN($(OUT)$(MODULE)/*.debug) CLEAN($(OUT)$(MODULE)/*.test)
+-clean: CLEAN($(OUT)$(MODULE)/*.depends)
+-clean: CLEAN($(OUT)$(MODULE)/*.gcno) CLEAN($(OUT)$(MODULE)/*.gcda)
+-clean: CLEAN($(OUT)$(MODULE)/*.gcov) CLEAN($(OUT)lcov-coverage.info)
+-clean: CLEAN($(OUT)lcov-html)
+-
+-$(info + submodule: $(MODULE_NAME))
+-# We must eval otherwise they may be dropped.
+-MODULE_C_OBJECTS = $(patsubst $(SRC)/$(MODULE)/%.c,$(MODULE)/%.o,\
+-  $(wildcard $(SRC)/$(MODULE)/*.c))
+-$(eval $(MODULE_NAME)_C_OBJECTS ?= $(MODULE_C_OBJECTS))
+-MODULE_CXX_OBJECTS = $(patsubst $(SRC)/$(MODULE)/%.cc,$(MODULE)/%.o,\
+-  $(wildcard $(SRC)/$(MODULE)/*.cc))
+-$(eval $(MODULE_NAME)_CXX_OBJECTS ?= $(MODULE_CXX_OBJECTS))
+-
+-# Note, $(MODULE) is implicit in the path to the %.c.
+-# See $(C_OBJECTS) for more details.
+-# Register rules for the module objects.
+-$(eval $(call add_object_rules,$(MODULE_C_OBJECTS),CC,c,CFLAGS,$(SRC)/))
+-$(eval $(call add_object_rules,$(MODULE_CXX_OBJECTS),CXX,cc,CXXFLAGS,$(SRC)/))
+-
+-# Continue recursive inclusion of module.mk files
+-SUBMODULE_DIRS = $(wildcard $(SRC)/$(MODULE)/*/module.mk)
+-include $(wildcard $(OUT)$(MODULE)/*.d)
+-include $(SUBMODULE_DIRS)
+-
+-endif
+-endif  ## pass-to-subcall wrapper for relocating the call directory
+diff --git a/fuzzers/modp_b64_decode_fuzzer.cc b/fuzzers/modp_b64_decode_fuzzer.cc
+new file mode 100644
+index 0000000..176ebc3
+--- /dev/null
++++ b/fuzzers/modp_b64_decode_fuzzer.cc
+@@ -0,0 +1,17 @@
++// Copyright 2019 The Chromium OS Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#include <string>
++#include <cstddef>
++#include <cstdint>
++
++#include "modp_b64.h"
++
++extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
++  // Create a buffer to store the output.
++  std::string buffer;
++  buffer.resize(modp_b64_decode_len(size));
++  modp_b64_decode(&(buffer[0]), (const char *) data, size);
++  return 0;
++}
+diff --git a/fuzzers/modp_b64_encode_fuzzer.cc b/fuzzers/modp_b64_encode_fuzzer.cc
+new file mode 100644
+index 0000000..0f61575
+--- /dev/null
++++ b/fuzzers/modp_b64_encode_fuzzer.cc
+@@ -0,0 +1,17 @@
++// Copyright 2019 The Chromium OS Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#include <string>
++#include <cstddef>
++#include <cstdint>
++
++#include "modp_b64.h"
++
++extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
++  // Create a buffer to store the output.
++  std::string buffer;
++  buffer.resize(modp_b64_encode_len(size));
++  modp_b64_encode(&buffer[0], (const char *)data, size);
++  return 0;
++}
+-- 
+2.23.0
+
diff --git a/pkgs/os-specific/linux/chromium-os/modp_b64/0002-Use-regular-archives.patch b/pkgs/os-specific/linux/chromium-os/modp_b64/0002-Use-regular-archives.patch
new file mode 100644
index 00000000000..57f087d5b16
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/modp_b64/0002-Use-regular-archives.patch
@@ -0,0 +1,36 @@
+From 11a6fc258c6765a43b973b15e86fb4bce7675202 Mon Sep 17 00:00:00 2001
+From: Manoj Gupta <manojgupta@google.com>
+Date: Mon, 14 Oct 2019 11:37:20 -0700
+Subject: [PATCH 2/2] Use regular archives.
+
+libmodp_b64 needs to be linked by libchrome later so
+use regular archives.
+
+BUG=chromium:1012803
+TEST=libchrome can link with libmodp_b64.
+
+Change-Id: Ie0bbcc8a54051d4136463c95762ba8343e487862
+---
+ BUILD.gn | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/BUILD.gn b/BUILD.gn
+index b2fe97d..9107609 100644
+--- a/BUILD.gn
++++ b/BUILD.gn
+@@ -16,6 +16,12 @@ group("all") {
+ }
+ 
+ static_library("modp_b64") {
++  configs -= [
++    "//common-mk:use_thin_archive",
++  ]
++  configs += [
++    "//common-mk:nouse_thin_archive",
++  ]
+   sources = [
+     "modp_b64.cc",
+     "modp_b64.h",
+-- 
+2.23.0
+
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..4908443f9b7
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/modp_b64/default.nix
@@ -0,0 +1,30 @@
+{ common-mk, lib, fetchFromGitiles, upstreamInfo }:
+
+common-mk {
+  platformSubdir = "modp_b64";
+
+  src = fetchFromGitiles upstreamInfo.components."aosp/platform/external/modp_b64";
+
+  patches = [
+    # We could just use the Makefile, but it's going to be removed in
+    # the next release anyway so let's just get on the GN train early.
+    ./0001-modp_b64-Fix-GN-build-and-add-fuzzers.patch
+    ./0002-Use-regular-archives.patch
+  ];
+
+  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/0010-sommelier-don-t-leak-source-absolute-paths.patch b/pkgs/os-specific/linux/chromium-os/sommelier/0010-sommelier-don-t-leak-source-absolute-paths.patch
new file mode 100644
index 00000000000..e2ca9fcdac3
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/sommelier/0010-sommelier-don-t-leak-source-absolute-paths.patch
@@ -0,0 +1,25 @@
+From b1a89637c458ea70ea0d280f1c2c469e177bfc6f Mon Sep 17 00:00:00 2001
+From: Alyssa Ross <hi@alyssa.is>
+Date: Sun, 1 Dec 2019 17:04:04 +0000
+Subject: [PATCH 10/10] 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 4f18a0c10..b1bd5d659 100644
+--- a/vm_tools/sommelier/wayland_protocol.gni
++++ b/vm_tools/sommelier/wayland_protocol.gni
+@@ -44,7 +44,7 @@ template("wayland_protocol_library") {
+         "wayland-scanner",
+         g.subcommand,
+         "{{source}}",
+-        output_file,
++        rebase_path(output_file),
+       ]
+     }
+   }
+-- 
+2.23.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..18137233719
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/sommelier/default.nix
@@ -0,0 +1,33 @@
+{ common-mk, lib
+, mesa, grpc, openssl, libdrm, xlibs, protobuf, wayland, libxkbcommon, vm_protos
+, libbrillo, libchrome, linuxHeaders, c-ares, zlib
+}:
+
+common-mk {
+  platformSubdir = "vm_tools/sommelier";
+
+  platform2Patches = [
+    ./0010-sommelier-don-t-leak-source-absolute-paths.patch
+  ];
+
+  buildInputs = [
+    mesa grpc openssl libdrm protobuf wayland libxkbcommon vm_protos libbrillo
+    libchrome linuxHeaders c-ares zlib
+  ] ++ (with xlibs; [ pixman libxcb libX11 ]);
+
+  NIX_CFLAGS_COMPILE = [
+    "-Wno-error=sign-compare"
+    "-Wno-error=class-memaccess"
+    "-Wno-error=maybe-uninitialized"
+  ];
+
+  installPhase = ''
+    mkdir -p $out/bin
+    install sommelier wayland_demo x11_demo $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 d00bffce3b8..136321e078e 100755
--- a/pkgs/applications/virtualization/crosvm/update.py
+++ b/pkgs/os-specific/linux/chromium-os/update.py
@@ -1,19 +1,29 @@
 #! /usr/bin/env nix-shell
-#! nix-shell -p python3 -p nix-prefetch-git -i python
+#! nix-shell -p python3 -i python
 
 import base64
 import csv
 import json
-import re
 import subprocess
 import xml.etree.ElementTree as ElementTree
 from codecs import iterdecode
 from operator import itemgetter
+from os import scandir
 from os.path import dirname, splitext
+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
+components = [
+    'aosp/platform/external/libchrome',
+    'aosp/platform/external/modp_b64',
+    'chromiumos/overlays/chromiumos-overlay',
+    'chromiumos/platform/crosvm',
+    'chromiumos/platform2',
+    'chromiumos/third_party/adhd',
+    'chromiumos/third_party/kernel',
+    'chromiumos/third_party/modemmanager-next',
+]
 
 git_root = 'https://chromium.googlesource.com/'
 manifest_versions = f'{git_root}chromiumos/manifest-versions'
@@ -32,8 +42,8 @@ with urlopen('https://cros-omahaproxy.appspot.com/all') as resp:
     stables = filter(lambda v: v['track'] == 'stable-channel', versions)
     stable = sorted(stables, key=itemgetter('chrome_version'), reverse=True)[0]
 
-chrome_major_version = re.match(r'\d+', stable['chrome_version'])[0]
-chromeos_tip_build = re.match(r'\d+', stable['chromeos_version'])[0]
+chrome_major_version = match(r'\d+', stable['chrome_version'])[0]
+chromeos_tip_build = match(r'\d+', stable['chromeos_version'])[0]
 
 # Find the most recent buildspec for the stable Chrome version and
 # Chromium OS build number.  Its branch build and branch branch build
@@ -62,24 +72,46 @@ with urlopen(f'{buildspecs_url}{chrome_major_version}/{buildspec}.xml?format=TEX
 # 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]]
+    name = component.split('/')[-1]
+    url = f'{git_root}{component}'
+    rev = revisions[component]
+    tarball = f'{url}/+archive/{rev}.tar.gz'
+    output = subprocess.check_output(['nix-prefetch-url', '--print-path', '--unpack', '--name', name, tarball])
+    (sha256, path) = output.decode('utf-8').splitlines()
+    paths[component] = path
+    data['components'][component] = {
+        'name': name,
+        'url': url,
+        'rev': rev,
+        'sha256': sha256,
+    }
 
-    output = subprocess.check_output(argv)
-    data['components'][component] = json.loads(output.decode('utf-8'))
+# Get the version number of libchrome.
+chromiumos_overlay = paths['chromiumos/overlays/chromiumos-overlay']
+contents = scandir(f'{chromiumos_overlay}/chromeos-base/libchrome')
+libchrome_version = lambda name: fullmatch(r'libchrome-(\d+)\.ebuild', name)[1]
+ebuilds = [f for f in contents if f.is_file(follow_symlinks=False)]
+versions = [libchrome_version(f.name) for f in ebuilds]
+latest = sorted(versions, key=int)[-1]
+data['components']['aosp/platform/external/libchrome']['version'] = latest
 
-# 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['chromiumos/third_party/kernel']
+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']['chromiumos/third_party/kernel']['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..50520c4881c
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/upstream-info.json
@@ -0,0 +1,55 @@
+{
+  "version": "78.12499.0.0-rc1",
+  "components": {
+    "aosp/platform/external/libchrome": {
+      "name": "libchrome",
+      "url": "https://chromium.googlesource.com/aosp/platform/external/libchrome",
+      "rev": "f4736afd702d3f9ac65a2810a1fc472d964941b7",
+      "sha256": "1wry24ma855rbjnawkjqyjjp4p4rsv6fa8i63mlg3pp5j7bflzip",
+      "version": "462023"
+    },
+    "aosp/platform/external/modp_b64": {
+      "name": "modp_b64",
+      "url": "https://chromium.googlesource.com/aosp/platform/external/modp_b64",
+      "rev": "afc3e28a3de4a627e3afaf73b4c55ed85c992470",
+      "sha256": "0cyvbdvnfcm958dglm0ci36v4np2fskkjxr8kzncgmhxpxdhkmwj"
+    },
+    "chromiumos/overlays/chromiumos-overlay": {
+      "name": "chromiumos-overlay",
+      "url": "https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay",
+      "rev": "63153be50fe6cbcd7126f9eed6b5bdda28526dae",
+      "sha256": "0v5b2mfrg8c927m073xhjcmgbn077s1gs36kvc7m23194y5wa75i"
+    },
+    "chromiumos/platform/crosvm": {
+      "name": "crosvm",
+      "url": "https://chromium.googlesource.com/chromiumos/platform/crosvm",
+      "rev": "0b86007d3e1ee400c6201c00b7dea323d661b50f",
+      "sha256": "1i3wf7f5ikly404ail161llghzw07wsalpdfdfpr5bs321yfkpsp"
+    },
+    "chromiumos/platform2": {
+      "name": "platform2",
+      "url": "https://chromium.googlesource.com/chromiumos/platform2",
+      "rev": "1a01bbebf957f4750021c6689eb65b9fc026338b",
+      "sha256": "1fyasgg2azixddnnsgfccnbjkpm2qbzjkvv22f298hv8qxhp32nr"
+    },
+    "chromiumos/third_party/adhd": {
+      "name": "adhd",
+      "url": "https://chromium.googlesource.com/chromiumos/third_party/adhd",
+      "rev": "72bf5919510c200fdd9a44ed223fd3a871908b49",
+      "sha256": "0fva5pfa8907qczf2lrinwbw60vvwfc9jv536p2lv86pb36q2vly"
+    },
+    "chromiumos/third_party/kernel": {
+      "name": "kernel",
+      "url": "https://chromium.googlesource.com/chromiumos/third_party/kernel",
+      "rev": "673c07c063fb4fc7d50078ba337e5acd7efca18c",
+      "sha256": "01qww3db1r5aw2r75xfv11qa8ysvwhcdw5sfmdwx1cc3l8j45m7g",
+      "version": "4.19.66"
+    },
+    "chromiumos/third_party/modemmanager-next": {
+      "name": "modemmanager-next",
+      "url": "https://chromium.googlesource.com/chromiumos/third_party/modemmanager-next",
+      "rev": "5b752047977b69618f1b31bd08fd38de6f4f5ba3",
+      "sha256": "0369khzax3r3nxf7jx7d2ryv14xi5s5dz60f4ml4cxidcca20xcj"
+    }
+  }
+}
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..5f40c5b416b
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/vm_protos/default.nix
@@ -0,0 +1,31 @@
+{ common-mk, lib, go-protobuf, grpc, openssl, protobuf }:
+
+common-mk {
+  pname = "vm_protos";
+  platformSubdir = "vm_tools/proto";
+
+  nativeBuildInputs = [ go-protobuf ];
+  buildInputs = [ grpc openssl protobuf ];
+
+  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/linux-cros-4.19.nix b/pkgs/os-specific/linux/kernel/linux-cros-4.19.nix
new file mode 100644
index 00000000000..626b0bbe6a9
--- /dev/null
+++ b/pkgs/os-specific/linux/kernel/linux-cros-4.19.nix
@@ -0,0 +1,34 @@
+{ stdenv, lib, buildPackages, fetchFromGitiles, upstreamInfo, perl, buildLinux
+, modDirVersionArg ? null
+, ... } @ args:
+
+let
+  versionData = upstreamInfo.components."chromiumos/third_party/kernel";
+in
+
+with lib;
+with import ../../../../lib/kernel.nix { inherit lib version; };
+
+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.
+    TCG_CR50_SPI = no;
+  } // (args.structuredExtraConfig or {});
+} // (args.argsOverride or {}))
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 011232db437..806159665d6 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -1489,8 +1489,6 @@ in
 
   crip = callPackage ../applications/audio/crip { };
 
-  crosvm = callPackage ../applications/virtualization/crosvm { };
-
   crunch = callPackage ../tools/security/crunch { };
 
   crudini = callPackage ../tools/misc/crudini { };
@@ -10852,6 +10850,11 @@ in
 
   chromaprint = callPackage ../development/libraries/chromaprint { };
 
+  chromiumOSPackages = recurseIntoAttrs
+    (callPackage ../os-specific/linux/chromium-os { });
+
+  inherit (chromiumOSPackages) crosvm sommelier;
+
   cl = callPackage ../development/libraries/cl { };
 
   classads = callPackage ../development/libraries/classads { };
@@ -16109,6 +16112,8 @@ in
 
   klibcShrunk = lowPrio (callPackage ../os-specific/linux/klibc/shrunk.nix { });
 
+  linux_cros = chromiumOSPackages.linux;
+
   linux_mptcp = linux_mptcp_95;
 
   linux_mptcp_94 = callPackage ../os-specific/linux/kernel/linux-mptcp-94.nix {
@@ -16409,6 +16414,7 @@ in
   linux_latest = linuxPackages_latest.kernel;
 
   # Build the kernel modules for the some of the kernels.
+  linuxPackages_cros = linuxPackagesFor pkgs.linux_cros;
   linuxPackages_mptcp = linuxPackagesFor pkgs.linux_mptcp;
   linuxPackages_rpi1 = linuxPackagesFor pkgs.linux_rpi1;
   linuxPackages_rpi2 = linuxPackagesFor pkgs.linux_rpi2;