summary refs log tree commit diff
path: root/pkgs/os-specific/linux/chromium-os
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2019-11-24 20:10:38 +0000
committerAlyssa Ross <hi@alyssa.is>2019-12-03 15:16:30 +0000
commit5f9876b29e6fd4e8ae9f0105a5386e932bedf3b6 (patch)
tree86178e84e3333b2f76af61740c5b90cfb961193b /pkgs/os-specific/linux/chromium-os
parent51fe75bdd32fa50b5e1b043957b71faf9260592f (diff)
downloadnixpkgs-5f9876b29e6fd4e8ae9f0105a5386e932bedf3b6.tar
nixpkgs-5f9876b29e6fd4e8ae9f0105a5386e932bedf3b6.tar.gz
nixpkgs-5f9876b29e6fd4e8ae9f0105a5386e932bedf3b6.tar.bz2
nixpkgs-5f9876b29e6fd4e8ae9f0105a5386e932bedf3b6.tar.lz
nixpkgs-5f9876b29e6fd4e8ae9f0105a5386e932bedf3b6.tar.xz
nixpkgs-5f9876b29e6fd4e8ae9f0105a5386e932bedf3b6.tar.zst
nixpkgs-5f9876b29e6fd4e8ae9f0105a5386e932bedf3b6.zip
sommelier: init at 78.12499.0.0-rc1
sommelier has a lot of dependencies on other Chromium OS packages.  To
manage this mess, I introduced chromiumOSPackages to hold them all,
since most of them won't be useful aside from building other
Chromium OS packages, and chromiumOSPackages.common-mk, which is a
wrapper around stdenv to handle interacting with Chromium OS's
idiosyncratic GN-based build system.

I adapted crosvm's updateScript to become the updateScript for all of
chromiumOSPackages, and pulled crosvm under chromiumOSPackages.  This
means that all Chromium OS packages use approximately the same
versions that are distributed as an upstream release.

There are still a couple of Chromium OS packages in Nixpkgs that
aren't part of this set.  Pulling those in is future work.
Diffstat (limited to 'pkgs/os-specific/linux/chromium-os')
-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.diff15
-rw-r--r--pkgs/os-specific/linux/chromium-os/crosvm/default.nix74
-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.py117
-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
28 files changed, 2721 insertions, 0 deletions
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/os-specific/linux/chromium-os/crosvm/default-seccomp-policy-dir.diff b/pkgs/os-specific/linux/chromium-os/crosvm/default-seccomp-policy-dir.diff
new file mode 100644
index 00000000000..f1aa50ee102
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/crosvm/default-seccomp-policy-dir.diff
@@ -0,0 +1,15 @@
+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),
++            seccomp_policy_dir: PathBuf::from(
++                option_env!("DEFAULT_SECCOMP_POLICY_DIR").unwrap_or(SECCOMP_POLICY_DIR),
++            ),
+             seccomp_log_failures: false,
+             cras_audio: false,
+             cras_capture: false,
diff --git a/pkgs/os-specific/linux/chromium-os/crosvm/default.nix b/pkgs/os-specific/linux/chromium-os/crosvm/default.nix
new file mode 100644
index 00000000000..648fef71616
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/crosvm/default.nix
@@ -0,0 +1,74 @@
+{ stdenv, rustPlatform, fetchFromGitiles, upstreamInfo
+, pkgconfig, minijail, dtc, libusb1, libcap
+}:
+
+let
+  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 = fetchFromGitiles
+    upstreamInfo.components."chromiumos/platform/crosvm";
+
+  adhdSrc = fetchFromGitiles
+    upstreamInfo.components."chromiumos/third_party/adhd";
+in
+
+  rustPlatform.buildRustPackage rec {
+    pname = "crosvm";
+    inherit (upstreamInfo) version;
+
+    unpackPhase = ''
+      runHook preUnpack
+
+      mkdir -p chromiumos/platform chromiumos/third_party
+
+      pushd chromiumos/platform
+      unpackFile ${crosvmSrc}
+      popd
+
+      pushd chromiumos/third_party
+      unpackFile ${adhdSrc}
+      popd
+
+      chmod -R u+w -- "$sourceRoot"
+
+      runHook postUnpack
+    '';
+
+    sourceRoot = "chromiumos/platform/crosvm";
+
+    patches = [
+      ./default-seccomp-policy-dir.diff
+    ];
+
+    cargoSha256 = "1b5i9gwrw55p89f7vwjy801q26hwyn8hd64w6qp66fl9fr7vgvbi";
+
+    nativeBuildInputs = [ pkgconfig ];
+
+    buildInputs = [ dtc libcap libusb1 minijail ];
+
+    postPatch = ''
+      sed -i "s|/usr/share/policy/crosvm/|$out/share/policy/|g" \
+             seccomp/*/*.policy
+    '';
+
+    preBuild = ''
+      export DEFAULT_SECCOMP_POLICY_DIR=$out/share/policy
+    '';
+
+    postInstall = ''
+      mkdir -p $out/share/policy/
+      cp seccomp/${arch}/* $out/share/policy/
+    '';
+
+    passthru.updateScript = ./update.py;
+
+    meta = with stdenv.lib; {
+      description = "A secure virtual machine monitor for KVM";
+      homepage = "https://chromium.googlesource.com/chromiumos/platform/crosvm/";
+      license = licenses.bsd3;
+      platforms = [ "aarch64-linux" "x86_64-linux" ];
+    };
+  }
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/os-specific/linux/chromium-os/update.py b/pkgs/os-specific/linux/chromium-os/update.py
new file mode 100755
index 00000000000..136321e078e
--- /dev/null
+++ b/pkgs/os-specific/linux/chromium-os/update.py
@@ -0,0 +1,117 @@
+#! /usr/bin/env nix-shell
+#! nix-shell -p python3 -i python
+
+import base64
+import csv
+import json
+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 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'
+buildspecs_url = f'{manifest_versions}/+/refs/heads/master/paladin/buildspecs/'
+
+# CrOS version numbers look like this:
+# [<chrome-major-version>.]<tip-build>.<branch-build>.<branch-branch-build>
+#
+# As far as I can tell, branches are where internal Google
+# modifications are added to turn Chromium OS into Chrome OS, and
+# branch branches are used for fixes for specific devices.  So for
+# Chromium OS they will always be 0.  This is a best guess, and is not
+# documented.
+with urlopen('https://cros-omahaproxy.appspot.com/all') as resp:
+    versions = csv.DictReader(iterdecode(resp, 'utf-8'))
+    stables = filter(lambda v: v['track'] == 'stable-channel', versions)
+    stable = sorted(stables, key=itemgetter('chrome_version'), reverse=True)[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
+# numbers will (almost?) certainly be 0.  It will then end with an rc
+# number -- presumably these are release candidates, one of which
+# becomes the final release.  Presumably the one with the highest rc
+# number.
+with urlopen(f'{buildspecs_url}{chrome_major_version}/?format=TEXT') as resp:
+    listing = base64.decodebytes(resp.read()).decode('utf-8')
+    buildspecs = [(line.split('\t', 1)[1]) for line in listing.splitlines()]
+    buildspecs = [s for s in buildspecs if s.startswith(chromeos_tip_build)]
+    buildspecs.sort(reverse=True)
+    buildspec = splitext(buildspecs[0])[0]
+
+revisions = {}
+
+# Read the buildspec, and extract the git revisions for each component.
+with urlopen(f'{buildspecs_url}{chrome_major_version}/{buildspec}.xml?format=TEXT') as resp:
+    xml = base64.decodebytes(resp.read()).decode('utf-8')
+    root = ElementTree.fromstring(xml)
+    for project in root.findall('project'):
+        revisions[project.get('name')] = project.get('revision')
+
+# Initialize the data that will be output from this script.  Leave the
+# rc number in buildspec so nobody else is subject to the same level
+# of confusion I have been.
+data = {'version': f'{chrome_major_version}.{buildspec}', 'components': {}}
+
+paths = {}
+
+# Fill in the 'components' dictionary with the output from
+# nix-prefetch-git, which can be passed straight to fetchGit when
+# imported by Nix.
+for component in components:
+    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,
+    }
+
+# 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
+
+# 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(__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;
+  };
+}