Add RootOfTrustCollection and RootOfTrust under Google service root.

These are Google only resources powered by Hoth DBus interface.
The ComponentsProtected links is hardcoded for now.
But it will be queried from DBus and interpreted accordingly in the
future.

TEST:
$curl -u root:0penBmc -X GET http://[::1]:$PORT/google/v1/RootOfTrustCollection
{
  "@odata.id": "/google/v1/RootOfTrustCollection",
  "@odata.type": "#RootOfTrustCollection.RootOfTrustCollection",
  "Members": [
    {
      "@odata.id": "/google/v1/RootOfTrustCollection/Hoth"
    }
  ],
  "Members@odata.count": 1
}

$ curl -u root:0penBmc -X GET http://[::1]:$PORT/google/v1/RootOfTrustCollection/Hoth
{
  "@odata.id": "/google/v1/RootOfTrustCollection/Hoth",
  "@odata.type": "#RootOfTrust.v1_0_0.RootOfTrust",
  "Actions": {
    "#RootOfTrust.SendCommand": {
      "target": "/google/v1/RootOfTrustCollection/Hoth/Actions/RootOfTrust.SendCommand"
    }
  },
  "Id": "Hoth",
  "Location": {
    "PartLocation": {
        "ServiceLabel": "Hoth",
        "Locationtype": "Embedded"
    }
  },
  "Name": "RootOfTrust-Hoth",
  "Status": {
    "State": "Enabled"
}

$ curl -u root:0penBmc -X POST -d @req.json -H "Content-Type: application/json" http://[::1]:$PORT/google/v1/RootOfTrustCollection/Hoth/Actions/RootOfTrust.SendCommand
{
  "CommandResponse": "033B0000"
}

Signed-off-by: Vidya Satyamsetti <satyamsetti@google.com>
Change-Id: If64612468bb89e6d9251d848697608b7daf37339
diff --git a/include/google/google_service_root.hpp b/include/google/google_service_root.hpp
index a80a500..42d2af9 100644
--- a/include/google/google_service_root.hpp
+++ b/include/google/google_service_root.hpp
@@ -2,26 +2,208 @@
 
 #include <app.hpp>
 #include <async_resp.hpp>
+#include <error_messages.hpp>
 #include <nlohmann/json.hpp>
+#include <utils/collection.hpp>
+#include <utils/hex_utils.hpp>
+#include <utils/json_utils.hpp>
+
+#include <vector>
 
 namespace crow
 {
 namespace google_api
 {
+constexpr const char* hothSearchPath = "/xyz/openbmc_project";
+constexpr const char* hothInterface = "xyz.openbmc_project.Control.Hoth";
+constexpr const char* rotCollectionPrefix = "/google/v1/RootOfTrustCollection";
+
+inline void getGoogleV1(const crow::Request& /*req*/,
+                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+    asyncResp->res.jsonValue["@odata.type"] =
+        "#GoogleServiceRoot.v1_0_0.GoogleServiceRoot";
+    asyncResp->res.jsonValue["@odata.id"] = "/google/v1";
+    asyncResp->res.jsonValue["Id"] = "Google Rest RootService";
+    asyncResp->res.jsonValue["Name"] = "Google Service Root";
+    asyncResp->res.jsonValue["Version"] = "1.0.0";
+    asyncResp->res.jsonValue["RootOfTrustCollection"]["@odata.id"] =
+        rotCollectionPrefix;
+}
+
+inline void getRootOfTrustCollection(
+    const crow::Request& /*req*/,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+    asyncResp->res.jsonValue["@odata.id"] = rotCollectionPrefix;
+    asyncResp->res.jsonValue["@odata.type"] =
+        "#RootOfTrustCollection.RootOfTrustCollection";
+    redfish::collection_util::getCollectionMembers(
+        asyncResp, rotCollectionPrefix, std::vector<const char*>{hothInterface},
+        hothSearchPath);
+}
+
+// Helper struct to identify a resolved D-Bus object interface
+struct ResolvedEntity
+{
+    std::string id;
+    std::string service;
+    std::string object;
+    const char* interface;
+};
+
+using ResolvedEntityHandler = std::function<void(
+    const std::string&, const std::shared_ptr<bmcweb::AsyncResp>&,
+    const ResolvedEntity&)>;
+
+inline void resolveRoT(const std::string& command,
+                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                       const std::string& rotId,
+                       ResolvedEntityHandler&& entityHandler)
+{
+    auto validateFunc = [command, asyncResp, rotId,
+                         entityHandler{std::forward<ResolvedEntityHandler>(
+                             entityHandler)}](
+                            const boost::system::error_code ec,
+                            const crow::openbmc_mapper::GetSubTreeType&
+                                subtree) {
+        if (ec)
+        {
+            redfish::messages::internalError(asyncResp->res);
+            return;
+        }
+        // Iterate over all retrieved ObjectPaths.
+        for (const std::pair<
+                 std::string,
+                 std::vector<std::pair<std::string, std::vector<std::string>>>>&
+                 object : subtree)
+        {
+            sdbusplus::message::object_path objPath(object.first);
+            if (objPath.filename() != rotId || object.second.empty())
+            {
+                continue;
+            }
+
+            ResolvedEntity resolvedEntity = {.id = rotId,
+                                             .service = object.second[0].first,
+                                             .object = object.first,
+                                             .interface = hothInterface};
+            entityHandler(command, asyncResp, resolvedEntity);
+            return;
+        }
+
+        // Couldn't find an object with that name.  return an error
+        redfish::messages::resourceNotFound(
+            asyncResp->res, "#RootOfTrust.v1_0_0.RootOfTrust", rotId);
+    };
+
+    std::array<std::string, 1> hothIfaces = {hothInterface};
+    crow::connections::systemBus->async_method_call(
+        validateFunc, "xyz.openbmc_project.ObjectMapper",
+        "/xyz/openbmc_project/object_mapper",
+        "xyz.openbmc_project.ObjectMapper", "GetSubTree", hothSearchPath,
+        /*depth=*/0, hothIfaces);
+}
+
+inline void populateRootOfTrustEntity(
+    const std::string& /*unused*/,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const ResolvedEntity& resolvedEntity)
+{
+    asyncResp->res.jsonValue["@odata.type"] = "#RootOfTrust.v1_0_0.RootOfTrust";
+    asyncResp->res.jsonValue["@odata.id"] =
+        "/google/v1/RootOfTrustCollection/" + resolvedEntity.id;
+
+    asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+    asyncResp->res.jsonValue["Id"] = resolvedEntity.id;
+    // Need to fix this later to a stabler property.
+    asyncResp->res.jsonValue["Name"] = resolvedEntity.id;
+    asyncResp->res.jsonValue["Description"] = "Google Root Of Trust";
+    asyncResp->res.jsonValue["Actions"]["#RootOfTrust.SendCommand"]["target"] =
+        "/google/v1/RootOfTrustCollection/" + resolvedEntity.id +
+        "/Actions/RootOfTrust.SendCommand";
+
+    asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
+        resolvedEntity.id;
+    asyncResp->res.jsonValue["Location"]["PartLocation"]["LocationType"] =
+        "Embedded";
+}
+
+inline void getRootOfTrust(const crow::Request& /*unused*/,
+                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                           const std::string& param)
+{
+    resolveRoT("" /*Empty command*/, asyncResp, param,
+               populateRootOfTrustEntity);
+}
+
+inline void
+    invokeRoTCommand(const std::string& command,
+                     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                     const ResolvedEntity& resolvedEntity)
+{
+    auto handleFunc = [asyncResp](const boost::system::error_code ec,
+                                  std::vector<uint8_t>& responseBytes) {
+        if (ec)
+        {
+            BMCWEB_LOG_ERROR << "RootOfTrust.Actions.SendCommand failed: "
+                             << ec.message();
+            redfish::messages::internalError(asyncResp->res);
+            return;
+        }
+
+        asyncResp->res.jsonValue["CommandResponse"] =
+            bytesToHexString(responseBytes);
+    };
+    std::vector<uint8_t> bytes = hexStringToBytes(command);
+    if (bytes.empty())
+    {
+        BMCWEB_LOG_DEBUG << "Invalid command: " << command;
+        redfish::messages::actionParameterValueTypeError(command, "Command",
+                                                         "SendCommand");
+        return;
+    }
+
+    crow::connections::systemBus->async_method_call(
+        handleFunc, resolvedEntity.service, resolvedEntity.object,
+        resolvedEntity.interface, "SendHostCommand", bytes);
+}
+
+inline void sendRoTCommand(const crow::Request& request,
+                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                           const std::string& rotId)
+{
+    std::string command;
+    if (!redfish::json_util::readJsonAction(request, asyncResp->res, "Command",
+                                            command))
+    {
+        BMCWEB_LOG_DEBUG << "Missing property Command.";
+        redfish::messages::actionParameterMissing(asyncResp->res, "SendCommand",
+                                                  "Command");
+        return;
+    }
+
+    resolveRoT(command, asyncResp, rotId, invokeRoTCommand);
+}
 
 inline void requestRoutes(App& app)
 {
     BMCWEB_ROUTE(app, "/google/v1/")
-        .methods(boost::beast::http::verb::get)(
-            [](const crow::Request&,
-               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
-                asyncResp->res.jsonValue["@odata.type"] =
-                    "#GoogleServiceRoot.v1_0_0.GoogleServiceRoot";
-                asyncResp->res.jsonValue["@odata.id"] = "/google/v1";
-                asyncResp->res.jsonValue["Id"] = "Google Rest RootService";
-                asyncResp->res.jsonValue["Name"] = "Google Service Root";
-                asyncResp->res.jsonValue["Version"] = "1.0.0";
-            });
+        .methods(boost::beast::http::verb::get)(getGoogleV1);
+
+    BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection")
+        .privileges({{"ConfigureManager"}})
+        .methods(boost::beast::http::verb::get)(getRootOfTrustCollection);
+
+    BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection/<str>")
+        .privileges({{"ConfigureManager"}})
+        .methods(boost::beast::http::verb::get)(getRootOfTrust);
+
+    BMCWEB_ROUTE(
+        app,
+        "/google/v1/RootOfTrustCollection/<str>/Actions/RootOfTrust.SendCommand")
+        .privileges({{"ConfigureManager"}})
+        .methods(boost::beast::http::verb::post)(sendRoTCommand);
 }
 
 } // namespace google_api
diff --git a/redfish-core/include/utils/hex_utils.hpp b/redfish-core/include/utils/hex_utils.hpp
index c7c89a5..0b3be2b 100644
--- a/redfish-core/include/utils/hex_utils.hpp
+++ b/redfish-core/include/utils/hex_utils.hpp
@@ -3,12 +3,14 @@
 #include <array>
 #include <cstddef>
 #include <string>
+#include <vector>
+
+static constexpr std::array<char, 16> digitsArray = {
+    '0', '1', '2', '3', '4', '5', '6', '7',
+    '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
 
 inline std::string intToHexString(uint64_t value, size_t digits)
 {
-    static constexpr std::array<char, 16> digitsArray = {
-        '0', '1', '2', '3', '4', '5', '6', '7',
-        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
     std::string rc(digits, '0');
     size_t bitIndex = (digits - 1) * 4;
     for (size_t digitIndex = 0; digitIndex < digits; digitIndex++)
@@ -18,3 +20,56 @@
     }
     return rc;
 }
+
+inline std::string bytesToHexString(const std::vector<uint8_t>& bytes)
+{
+    std::string rc(bytes.size() * 2, '0');
+    for (size_t i = 0; i < bytes.size(); ++i)
+    {
+        rc[i * 2] = digitsArray[(bytes[i] & 0xf0) >> 4];
+        rc[i * 2 + 1] = digitsArray[bytes[i] & 0x0f];
+    }
+    return rc;
+}
+
+// Returns nibble.
+inline uint8_t hexCharToNibble(char ch)
+{
+    uint8_t rc = 16;
+    if (ch >= '0' && ch <= '9')
+    {
+        rc = static_cast<uint8_t>(ch) - '0';
+    }
+    else if (ch >= 'A' && ch <= 'F')
+    {
+        rc = static_cast<uint8_t>(ch) - 'A' + 10;
+    }
+    else if (ch >= 'a' && ch <= 'f')
+    {
+        rc = static_cast<uint8_t>(ch) - 'a' + 10;
+    }
+
+    return rc;
+}
+
+// Returns empty vector in case of malformed hex-string.
+inline std::vector<uint8_t> hexStringToBytes(const std::string& str)
+{
+    std::vector<uint8_t> rc(str.size() / 2, 0);
+    for (size_t i = 0; i < str.length(); i += 2)
+    {
+        uint8_t hi = hexCharToNibble(str[i]);
+        if (i == str.length() - 1)
+        {
+            return {};
+        }
+        uint8_t lo = hexCharToNibble(str[i + 1]);
+        if (lo == 16 || hi == 16)
+        {
+            return {};
+        }
+
+        rc[i / 2] = static_cast<uint8_t>(hi << 4) | lo;
+    }
+    return rc;
+}
diff --git a/redfish-core/ut/hex_utils_test.cpp b/redfish-core/ut/hex_utils_test.cpp
index 623c065..5084b8b 100644
--- a/redfish-core/ut/hex_utils_test.cpp
+++ b/redfish-core/ut/hex_utils_test.cpp
@@ -23,3 +23,45 @@
     EXPECT_EQ(intToHexString(0xBEEF, 3), "EEF");
     EXPECT_EQ(intToHexString(0xBEEF, 4), "BEEF");
 }
+
+TEST(BytesToHexString, Success)
+{
+    EXPECT_EQ(bytesToHexString({0x1a, 0x2b}), "1A2B");
+}
+
+TEST(HexCharToNibble, chars)
+{
+    for (char c = 0; c < CHAR_MAX; ++c)
+    {
+        uint8_t expected = 16;
+        if (isdigit(c) != 0)
+        {
+            expected = static_cast<uint8_t>(c) - '0';
+        }
+        else if (c >= 'A' && c <= 'F')
+        {
+            expected = static_cast<uint8_t>(c) - 'A' + 10;
+        }
+        else if (c >= 'a' && c <= 'f')
+        {
+            expected = static_cast<uint8_t>(c) - 'a' + 10;
+        }
+
+        EXPECT_EQ(hexCharToNibble(c), expected);
+    }
+}
+
+TEST(HexStringToBytes, Success)
+{
+    std::vector<uint8_t> hexBytes = {0x01, 0x23, 0x45, 0x67,
+                                     0x89, 0xAB, 0xCD, 0xEF};
+    EXPECT_EQ(hexStringToBytes("0123456789ABCDEF"), hexBytes);
+    EXPECT_TRUE(hexStringToBytes("").empty());
+}
+
+TEST(HexStringToBytes, Failure)
+{
+    EXPECT_TRUE(hexStringToBytes("Hello").empty());
+    EXPECT_TRUE(hexStringToBytes("`").empty());
+    EXPECT_TRUE(hexStringToBytes("012").empty());
+}
diff --git a/static/google/v1/$metadata/index.xml b/static/google/v1/$metadata/index.xml
index 57a64af..9cd9c37 100644
--- a/static/google/v1/$metadata/index.xml
+++ b/static/google/v1/$metadata/index.xml
@@ -3,5 +3,13 @@
     <edmx:Reference Uri="/google/v1/schema/ServiceRoot_v1.xml">
         <edmx:Include Namespace="GoogleServiceRoot"/>
         <edmx:Include Namespace="GoogleServiceRoot.v1_0_0"/>
+
+    <edmx:Reference Uri="/google/v1/schema/RootOfTrustCollection_v1.xml">
+        <edmx:Include Namespace="RootOfTrustCollection"/>
+    </edmx:Reference>
+    <edmx:Reference Uri="/google/v1/schema/RootOfTrust_v1.xml">
+        <edmx:Include Namespace="RootOfTrust"/>
+        <edmx:Include Namespace="RootOfTrust.v1_0_0"/>
+    </edmx:Reference>
     </edmx:Reference>
 </edmx:Edmx>
diff --git a/static/google/v1/odata/index.json b/static/google/v1/odata/index.json
index 3b5896b..8b00f37 100644
--- a/static/google/v1/odata/index.json
+++ b/static/google/v1/odata/index.json
@@ -20,6 +20,11 @@
             "kind": "Singleton",
             "name": "ServiceRoot",
             "url": "/google/v1/ServiceRoot"
+        },
+        {
+            "kind": "Singleton",
+            "name": "RootOfTrustCollection",
+            "url": "/google/v1/RootOfTrustCollection"
         }
     ]
 }
diff --git a/static/google/v1/schema/RootOfTrustCollection_v1.xml b/static/google/v1/schema/RootOfTrustCollection_v1.xml
new file mode 100644
index 0000000..62ed1cb
--- /dev/null
+++ b/static/google/v1/schema/RootOfTrustCollection_v1.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!---->
+<!--################################################################################       -->
+<!--# Redfish Schema:  RootOfTrustCollection                                          -->
+<!--#                                                                                      -->
+<!--# For a detailed change log, see the README file contained in the DSP8010 bundle,      -->
+<!--# available at http://www.dmtf.org/standards/redfish                                   -->
+<!--# Copyright 2014-2021 DMTF.                                                            -->
+<!--# For the full DMTF copyright policy, see http://www.dmtf.org/about/policies/copyright -->
+<!--################################################################################       -->
+<!---->
+<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
+
+  <edmx:Reference Uri="http://docs.oasis-open.org/odata/odata/v4.0/errata03/csd01/complete/vocabularies/Org.OData.Core.V1.xml">
+    <edmx:Include Namespace="Org.OData.Core.V1" Alias="OData"/>
+  </edmx:Reference>
+  <edmx:Reference Uri="http://docs.oasis-open.org/odata/odata/v4.0/errata03/csd01/complete/vocabularies/Org.OData.Capabilities.V1.xml">
+    <edmx:Include Namespace="Org.OData.Capabilities.V1" Alias="Capabilities"/>
+  </edmx:Reference>
+  <edmx:Reference Uri="http://redfish.dmtf.org/schemas/v1/Resource_v1.xml">
+    <edmx:Include Namespace="Resource.v1_0_0"/>
+  </edmx:Reference>
+  <edmx:Reference Uri="http://redfish.dmtf.org/schemas/v1/RedfishExtensions_v1.xml">
+    <edmx:Include Namespace="RedfishExtensions.v1_0_0" Alias="Redfish"/>
+  </edmx:Reference>
+
+  <edmx:DataServices>
+
+    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="RootOfTrustCollection">
+      <Annotation Term="Redfish.OwningEntity" String="Google"/>
+      <EntityType Name="RootOfTrustCollection" BaseType="Resource.v1_0_0.ResourceCollection">
+        <Annotation Term="OData.Description" String="The RootOfTrustCollection schema describes a Resource Collection of RootOfTrust instances."/>
+        <Annotation Term="OData.LongDescription" String="This Resource shall represent a Resource Collection of RootOfTrust instances for a Redfish implementation."/>
+        <NavigationProperty Name="Members" Type="Collection(RootOfTrust.RootOfTrust)">
+          <Annotation Term="OData.Permissions" EnumMember="OData.Permission/Read"/>
+          <Annotation Term="OData.Description" String="The members of this collection."/>
+          <Annotation Term="OData.LongDescription" String="This property shall contain an array of links to the members of this collection."/>
+          <Annotation Term="Redfish.Required"/>
+        </NavigationProperty>
+      </EntityType>
+
+    </Schema>
+  </edmx:DataServices>
+</edmx:Edmx>
diff --git a/static/google/v1/schema/RootOfTrust_v1.xml b/static/google/v1/schema/RootOfTrust_v1.xml
new file mode 100644
index 0000000..ad76700
--- /dev/null
+++ b/static/google/v1/schema/RootOfTrust_v1.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!---->
+<!--################################################################################       -->
+<!--# Redfish Schema:  RootOfTrust v1.0.0                                           -->
+<!--#                                                                                      -->
+<!--# For a detailed change log, see the README file contained in the DSP8010 bundle,      -->
+<!--# available at http://www.dmtf.org/standards/redfish                                   -->
+<!--# Copyright 2014-2021 DMTF.                                                            -->
+<!--# For the full DMTF copyright policy, see http://www.dmtf.org/about/policies/copyright -->
+<!--################################################################################       -->
+<!---->
+<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
+
+  <edmx:Reference Uri="http://docs.oasis-open.org/odata/odata/v4.0/errata03/csd01/complete/vocabularies/Org.OData.Core.V1.xml">
+    <edmx:Include Namespace="Org.OData.Core.V1" Alias="OData"/>
+  </edmx:Reference>
+  <edmx:Reference Uri="http://docs.oasis-open.org/odata/odata/v4.0/errata03/csd01/complete/vocabularies/Org.OData.Capabilities.V1.xml">
+    <edmx:Include Namespace="Org.OData.Capabilities.V1" Alias="Capabilities"/>
+  </edmx:Reference>
+  <edmx:Reference Uri="http://redfish.dmtf.org/schemas/v1/RedfishExtensions_v1.xml">
+    <edmx:Include Namespace="Validation.v1_0_0" Alias="Validation"/>
+    <edmx:Include Namespace="RedfishExtensions.v1_0_0" Alias="Redfish"/>
+  </edmx:Reference>
+  <edmx:Reference Uri="http://redfish.dmtf.org/schemas/v1/Resource_v1.xml">
+    <edmx:Include Namespace="Resource"/>
+    <edmx:Include Namespace="Resource.v1_0_0"/>
+  </edmx:Reference>
+
+  <edmx:DataServices>
+
+    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="RootOfTrust">
+      <Annotation Term="Redfish.OwningEntity" String="Google"/>
+
+      <EntityType Name="RootOfTrust" BaseType="Resource.v1_0_0.Resource" Abstract="true">
+        <Annotation Term="OData.Description" String="The RootOfTrust resource represents a trusted physical entity."/>
+        <Annotation Term="OData.LongDescription" String="This resource shall represent a trusted physical entity."/>
+      </EntityType>
+
+    </Schema>
+
+    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="RootOfTrust.v1_0_0">
+      <Annotation Term="Redfish.OwningEntity" String="Google"/>
+
+      <EntityType Name="RootOfTrust" BaseType="RootOfTrust.RootOfTrust">
+        <Property Name="Actions" Type="RootOfTrust.v1_0_0.Actions" Nullable="false">
+          <Annotation Term="OData.Description" String="The available actions for this resource."/>
+          <Annotation Term="OData.LongDescription" String="This property shall contain the available actions for this resource."/>
+        </Property>
+      </EntityType>
+
+      <ComplexType Name="Actions">
+        <Annotation Term="OData.AdditionalProperties" Bool="false"/>
+        <Annotation Term="OData.Description" String="The available actions for this resource."/>
+        <Annotation Term="OData.LongDescription" String="This type shall contain the available actions for this resource."/>
+      </ComplexType>
+
+     <Action Name="SendCommand" IsBound="true">
+        <Annotation Term="OData.Description" String="This action sends commands to trusted component."/>
+        <Annotation Term="OData.LongDescription" String="This action shall send hoth commands to trusted component."/>
+        <Parameter Name="RootOfTrust" Type="RootOfTrust.v1_0_0.Actions"/>
+        <Parameter Name="Command" Type="Edm.String" Nullable="false"/>
+          <Annotation Term="OData.Description" String="The bytes to forward to the root of trust device."/>
+          <Annotation Term="OData.LongDescription" String="This parameter shall contain the bytes to be forwarded to the root of trust device. The string should be a hex-encoded string, for instance '0100'. Each byte shall be encoded as a 2-character hex."/>
+        <ReturnType Name="CommandResponse" Type="Edm.String"/>
+          <Annotation Term="OData.Description" String="The bytes returned by the root of trust device."/>
+          <Annotation Term="OData.LongDescription" String="This return value shall contain the bytes returned by the root of trust device. The string should be a hex-encoded string, for instance '0100'. Each byte shall be encoded as a 2-character hex."/>
+      </Action>
+    </Schema>
+
+  </edmx:DataServices>
+</edmx:Edmx>
diff --git a/static/google/v1/schema/ServiceRoot_v1.xml b/static/google/v1/schema/ServiceRoot_v1.xml
index 59771b6..09dc8b1 100644
--- a/static/google/v1/schema/ServiceRoot_v1.xml
+++ b/static/google/v1/schema/ServiceRoot_v1.xml
@@ -5,7 +5,7 @@
 <!--#                                                                                      -->
 <!--################################################################################       -->
 <!---->
-<edmx:Edmx Version="1.0">
+<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
 
   <edmx:DataServices>
 
@@ -38,6 +38,11 @@
           <Annotation Term="OData.LongDescription" String="This property shall contain a link to a Resource Collection of type JsonSchemaFileCollection."/>
           <Annotation Term="OData.AutoExpandReferences"/>
         </NavigationProperty>
+        <NavigationProperty Name="RootOfTrustCollection" Type="RootOfTrustCollection.RootOfTrustCollection" Nullable="false">
+          <Annotation Term="OData.Permissions" EnumMember="OData.Permission/Read"/>
+          <Annotation Term="OData.Description" String="The link to a Google Root Of Trust collection."/>
+          <Annotation Term="OData.LongDescription" String="This property shall contain a link to a Google RootOfTrust collection."/>
+        </NavigationProperty>
       </EntityType>
 
     </Schema>