From 1aca8b72694fcbefc4f31bf49f41e7491ad29db4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 5 Apr 2019 11:56:44 -0700 Subject: [PATCH] protos: Compile protos for trunks daemon The TPM device will need these protos to communicate TPM commands to the Trunks daemon and receive TPM responses. BUG=chromium:911799 TEST=cargo check TEST=cargo check --features tpm TEST=FEATURES=test emerge-nami crosvm TEST=FEATURES=test USE=crosvm-tpm emerge-nami crosvm TEST=local kokoro CQ-DEPEND=CL:1553610 CQ-DEPEND=CL:1553971 Change-Id: I1a67a7b4a3714236b20a790068ca19129446f71c Reviewed-on: https://chromium-review.googlesource.com/1554982 Commit-Ready: ChromeOS CL Exonerator Bot Tested-by: David Tolnay Tested-by: kokoro Reviewed-by: David Tolnay Reviewed-by: Zach Reizner Reviewed-by: Daniel Verkamp --- Cargo.lock | 9 +++++ devices/Cargo.toml | 3 +- protos/Cargo.toml | 11 ++++++ protos/build.rs | 78 ++++++++++++++++++++++++++++++++++++++ protos/src/lib.rs | 5 +++ protos/tests/common/mod.rs | 35 +++++++++++++++++ protos/tests/trunks.rs | 22 +++++++++++ 7 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 protos/Cargo.toml create mode 100644 protos/build.rs create mode 100644 protos/src/lib.rs create mode 100644 protos/tests/common/mod.rs create mode 100644 protos/tests/trunks.rs diff --git a/Cargo.lock b/Cargo.lock index 1b28355012..19667d111a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -152,6 +152,7 @@ dependencies = [ "net_sys 0.1.0", "net_util 0.1.0", "p9 0.1.0", + "protos 0.1.0", "resources 0.1.0", "sync 0.1.0", "sys_util 0.1.0", @@ -384,6 +385,14 @@ dependencies = [ "tempfile 3.0.7", ] +[[package]] +name = "protos" +version = "0.1.0" +dependencies = [ + "protobuf 2.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "protoc-rust 2.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "qcow" version = "0.1.0" diff --git a/devices/Cargo.toml b/devices/Cargo.toml index c1ddad0f34..d916df82f1 100644 --- a/devices/Cargo.toml +++ b/devices/Cargo.toml @@ -6,7 +6,7 @@ authors = ["The Chromium OS Authors"] [features] gpu = ["gpu_buffer", "gpu_display", "gpu_renderer"] sandboxed-libusb = ["usb_util/sandboxed-libusb"] -tpm = ["tpm2"] +tpm = ["protos", "tpm2"] wl-dmabuf = [] [dependencies] @@ -26,6 +26,7 @@ msg_socket = { path = "../msg_socket" } net_sys = { path = "../net_sys" } net_util = { path = "../net_util" } p9 = { path = "../p9" } +protos = { path = "../protos", optional = true } resources = { path = "../resources" } sync = { path = "../sync" } sys_util = { path = "../sys_util" } diff --git a/protos/Cargo.toml b/protos/Cargo.toml new file mode 100644 index 0000000000..1bc2c4914e --- /dev/null +++ b/protos/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "protos" +version = "0.1.0" +authors = ["The Chromium OS Authors"] +edition = "2018" + +[dependencies] +protobuf = "2.3" + +[build-dependencies] +protoc-rust = "2.3" diff --git a/protos/build.rs b/protos/build.rs new file mode 100644 index 0000000000..f4f5d971ee --- /dev/null +++ b/protos/build.rs @@ -0,0 +1,78 @@ +// 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. + +use std::env; +use std::error::Error; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +type Result = std::result::Result>; + +struct Proto { + // Where to find protos during builds within cros_sdk. Relative to $SYSROOT + // environment variable set by emerge builds. + dir_relative_to_sysroot: &'static str, + + // Where to find protos during "cargo build" in a local developer + // environment. Relative to the platform/crosvm/protos directory. + dir_relative_to_us: &'static str, + + // *.proto file expected to exist in both of the above directories. + proto_file_name: &'static str, + + // Code generated by proto compiler will be exported under + // protos::$module_name. + name_for_module: &'static str, +} + +static PROTOS: &[Proto] = &[Proto { + dir_relative_to_sysroot: "usr/include/chromeos/dbus/trunks", + dir_relative_to_us: "../../../platform2/trunks", + proto_file_name: "interface.proto", + name_for_module: "trunks", +}]; + +fn paths_to_strs(paths: &[PathBuf]) -> Vec<&str> { + paths + .iter() + .map(|p| p.as_os_str().to_str().unwrap()) + .collect() +} + +fn main() -> Result<()> { + let out_dir = env::var("OUT_DIR")?; + let sysroot = env::var_os("SYSROOT"); + + // Write out a Rust module that imports the modules generated by protoc. + let protos_rs = PathBuf::from(&out_dir).join("protos.rs"); + let mut out = File::create(protos_rs)?; + + let mut input_files = Vec::new(); + let mut include_dirs = Vec::new(); + + for proto in PROTOS { + let dir = match &sysroot { + Some(dir) => PathBuf::from(dir).join(proto.dir_relative_to_sysroot), + None => PathBuf::from(proto.dir_relative_to_us), + }; + + input_files.push(dir.join(proto.proto_file_name)); + include_dirs.push(dir); + + let generated_module = proto.proto_file_name.replace(".proto", ""); + writeln!(out, "#[path = \"{}/{}.rs\"]", out_dir, generated_module)?; + writeln!(out, "pub mod {};", proto.name_for_module)?; + } + + // Invoke proto compiler. + protoc_rust::run(protoc_rust::Args { + out_dir: &out_dir, + input: &paths_to_strs(&input_files), + includes: &paths_to_strs(&include_dirs), + ..Default::default() + })?; + + Ok(()) +} diff --git a/protos/src/lib.rs b/protos/src/lib.rs new file mode 100644 index 0000000000..5381935f02 --- /dev/null +++ b/protos/src/lib.rs @@ -0,0 +1,5 @@ +// 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!(concat!(env!("OUT_DIR"), "/protos.rs")); diff --git a/protos/tests/common/mod.rs b/protos/tests/common/mod.rs new file mode 100644 index 0000000000..a5aaf0735f --- /dev/null +++ b/protos/tests/common/mod.rs @@ -0,0 +1,35 @@ +// 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. + +use protobuf::Message; + +/// Asserts that a given protobuf message object can be serialized to bytes and +/// read back into a value of the same type, preserving equality between the +/// original object and the one read back. +/// +/// This is helpful for confirming that proto files have been compiled +/// successfully and are exposed as intended by the public API of the parent +/// crate. It also lets us exercise the full set of methods we intend to use for +/// building particular proto objects so that we notice breakage early in the +/// event that a proto external to this repository would make a breaking change. +/// +/// Note: assumes that the given `message` is not just `T::new` so that we can +/// tell that deserialization has happened successfully. +/// +/// # Example +/// +/// ```ignore +/// let mut request = SendCommandRequest::new(); +/// request.set_command(b"...".to_vec()); +/// test_round_trip(request); +/// ``` +pub fn test_round_trip(message: T) { + let serialized = message.write_to_bytes().unwrap(); + + let mut back = T::new(); + assert_ne!(message, back); + + back.merge_from_bytes(&serialized).unwrap(); + assert_eq!(message, back); +} diff --git a/protos/tests/trunks.rs b/protos/tests/trunks.rs new file mode 100644 index 0000000000..574c11082d --- /dev/null +++ b/protos/tests/trunks.rs @@ -0,0 +1,22 @@ +// 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. + +mod common; + +use crate::common::test_round_trip; +use protos::trunks::{SendCommandRequest, SendCommandResponse}; + +#[test] +fn send_command_request() { + let mut request = SendCommandRequest::new(); + request.set_command(b"...".to_vec()); + test_round_trip(request); +} + +#[test] +fn send_command_response() { + let mut response = SendCommandResponse::new(); + response.set_response(b"...".to_vec()); + test_round_trip(response); +}