blob: f14cffe20bc65e8019a851c4582d43df69010e73 [file] [log] [blame]
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -07001#pragma once
2
3#include <app.hpp>
4#include <async_resp.hpp>
Jiaqing Zhaob6a55182022-05-20 11:47:46 +08005#include <dbus_utility.hpp>
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -07006#include <error_messages.hpp>
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -07007#include <nlohmann/json.hpp>
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -07008#include <utils/collection.hpp>
9#include <utils/hex_utils.hpp>
10#include <utils/json_utils.hpp>
11
George Liu7a1dbc42022-12-07 16:03:22 +080012#include <array>
13#include <string_view>
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070014#include <vector>
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -070015
16namespace crow
17{
18namespace google_api
19{
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070020
Nan Zhou30aacdd2022-07-03 05:02:36 +000021inline void
22 handleGoogleV1Get(const crow::Request& /*req*/,
23 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070024{
25 asyncResp->res.jsonValue["@odata.type"] =
26 "#GoogleServiceRoot.v1_0_0.GoogleServiceRoot";
27 asyncResp->res.jsonValue["@odata.id"] = "/google/v1";
28 asyncResp->res.jsonValue["Id"] = "Google Rest RootService";
29 asyncResp->res.jsonValue["Name"] = "Google Service Root";
30 asyncResp->res.jsonValue["Version"] = "1.0.0";
31 asyncResp->res.jsonValue["RootOfTrustCollection"]["@odata.id"] =
Nan Zhoucd027592022-07-03 05:18:29 +000032 "/google/v1/RootOfTrustCollection";
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070033}
34
Nan Zhou30aacdd2022-07-03 05:02:36 +000035inline void handleRootOfTrustCollectionGet(
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070036 const crow::Request& /*req*/,
37 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
38{
Nan Zhoucd027592022-07-03 05:18:29 +000039 asyncResp->res.jsonValue["@odata.id"] = "/google/v1/RootOfTrustCollection";
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070040 asyncResp->res.jsonValue["@odata.type"] =
41 "#RootOfTrustCollection.RootOfTrustCollection";
George Liu7a1dbc42022-12-07 16:03:22 +080042 const std::array<std::string_view, 1> interfaces{
43 "xyz.openbmc_project.Control.Hoth"};
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070044 redfish::collection_util::getCollectionMembers(
Willy Tuae9031f2022-09-27 05:48:07 +000045 asyncResp, boost::urls::url("/google/v1/RootOfTrustCollection"),
George Liu7a1dbc42022-12-07 16:03:22 +080046 interfaces, "/xyz/openbmc_project");
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070047}
48
49// Helper struct to identify a resolved D-Bus object interface
50struct ResolvedEntity
51{
52 std::string id;
53 std::string service;
54 std::string object;
Nan Zhou16a55352022-07-03 05:06:08 +000055 std::string interface;
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070056};
57
58using ResolvedEntityHandler = std::function<void(
59 const std::string&, const std::shared_ptr<bmcweb::AsyncResp>&,
60 const ResolvedEntity&)>;
61
Nan Zhou30aacdd2022-07-03 05:02:36 +000062inline void hothGetSubtreeCallback(
63 const std::string& command,
64 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
65 const std::string& rotId, const ResolvedEntityHandler& entityHandler,
66 const boost::system::error_code ec,
67 const dbus::utility::MapperGetSubTreeResponse& subtree)
68{
69 if (ec)
70 {
71 redfish::messages::internalError(asyncResp->res);
72 return;
73 }
Nan Zhou5600f022022-07-03 16:22:38 +000074 for (const auto& [path, services] : subtree)
Nan Zhou30aacdd2022-07-03 05:02:36 +000075 {
Nan Zhou5600f022022-07-03 16:22:38 +000076 sdbusplus::message::object_path objPath(path);
77 if (objPath.filename() != rotId || services.empty())
Nan Zhou30aacdd2022-07-03 05:02:36 +000078 {
79 continue;
80 }
81
Nan Zhoucd027592022-07-03 05:18:29 +000082 ResolvedEntity resolvedEntity = {
83 .id = rotId,
Nan Zhou5600f022022-07-03 16:22:38 +000084 .service = services[0].first,
85 .object = path,
Nan Zhoucd027592022-07-03 05:18:29 +000086 .interface = "xyz.openbmc_project.Control.Hoth"};
Nan Zhou30aacdd2022-07-03 05:02:36 +000087 entityHandler(command, asyncResp, resolvedEntity);
88 return;
89 }
90
91 // Couldn't find an object with that name. return an error
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +080092 redfish::messages::resourceNotFound(asyncResp->res, "RootOfTrust", rotId);
Nan Zhou30aacdd2022-07-03 05:02:36 +000093}
94
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070095inline void resolveRoT(const std::string& command,
96 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
97 const std::string& rotId,
98 ResolvedEntityHandler&& entityHandler)
99{
Nan Zhou30aacdd2022-07-03 05:02:36 +0000100
George Liu7a1dbc42022-12-07 16:03:22 +0800101 constexpr std::array<std::string_view, 1> hothIfaces = {
Nan Zhoucd027592022-07-03 05:18:29 +0000102 "xyz.openbmc_project.Control.Hoth"};
Nan Zhou30aacdd2022-07-03 05:02:36 +0000103 crow::connections::systemBus->async_method_call(
Ed Tanous002d39b2022-05-31 08:59:27 -0700104 [command, asyncResp, rotId,
105 entityHandler{std::forward<ResolvedEntityHandler>(entityHandler)}](
106 const boost::system::error_code ec,
107 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Nan Zhou30aacdd2022-07-03 05:02:36 +0000108 hothGetSubtreeCallback(command, asyncResp, rotId, entityHandler, ec,
109 subtree);
110 },
111 "xyz.openbmc_project.ObjectMapper",
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700112 "/xyz/openbmc_project/object_mapper",
Nan Zhoucd027592022-07-03 05:18:29 +0000113 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
114 "/xyz/openbmc_project",
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700115 /*depth=*/0, hothIfaces);
116}
117
118inline void populateRootOfTrustEntity(
119 const std::string& /*unused*/,
120 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
121 const ResolvedEntity& resolvedEntity)
122{
123 asyncResp->res.jsonValue["@odata.type"] = "#RootOfTrust.v1_0_0.RootOfTrust";
124 asyncResp->res.jsonValue["@odata.id"] =
125 "/google/v1/RootOfTrustCollection/" + resolvedEntity.id;
126
127 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
128 asyncResp->res.jsonValue["Id"] = resolvedEntity.id;
129 // Need to fix this later to a stabler property.
130 asyncResp->res.jsonValue["Name"] = resolvedEntity.id;
131 asyncResp->res.jsonValue["Description"] = "Google Root Of Trust";
132 asyncResp->res.jsonValue["Actions"]["#RootOfTrust.SendCommand"]["target"] =
133 "/google/v1/RootOfTrustCollection/" + resolvedEntity.id +
134 "/Actions/RootOfTrust.SendCommand";
135
136 asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
137 resolvedEntity.id;
138 asyncResp->res.jsonValue["Location"]["PartLocation"]["LocationType"] =
139 "Embedded";
140}
141
Nan Zhou30aacdd2022-07-03 05:02:36 +0000142inline void
143 handleRootOfTrustGet(const crow::Request& /*req*/,
144 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
145 const std::string& param)
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700146{
Nan Zhou30aacdd2022-07-03 05:02:36 +0000147 std::string emptyCommand;
148 resolveRoT(emptyCommand, asyncResp, param, populateRootOfTrustEntity);
149}
150
151inline void
152 invocationCallback(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
153 const boost::system::error_code ec,
154 const std::vector<uint8_t>& responseBytes)
155{
156 if (ec)
157 {
158 BMCWEB_LOG_ERROR << "RootOfTrust.Actions.SendCommand failed: "
159 << ec.message();
160 redfish::messages::internalError(asyncResp->res);
161 return;
162 }
163
164 asyncResp->res.jsonValue["CommandResponse"] =
165 bytesToHexString(responseBytes);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700166}
167
168inline void
169 invokeRoTCommand(const std::string& command,
170 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
171 const ResolvedEntity& resolvedEntity)
172{
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700173 std::vector<uint8_t> bytes = hexStringToBytes(command);
174 if (bytes.empty())
175 {
176 BMCWEB_LOG_DEBUG << "Invalid command: " << command;
177 redfish::messages::actionParameterValueTypeError(command, "Command",
178 "SendCommand");
179 return;
180 }
181
182 crow::connections::systemBus->async_method_call(
Nan Zhou30aacdd2022-07-03 05:02:36 +0000183 [asyncResp{asyncResp}](const boost::system::error_code ec,
184 const std::vector<uint8_t>& responseBytes) {
185 invocationCallback(asyncResp, ec, responseBytes);
186 },
187 resolvedEntity.service, resolvedEntity.object, resolvedEntity.interface,
188 "SendHostCommand", bytes);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700189}
190
Nan Zhou30aacdd2022-07-03 05:02:36 +0000191inline void handleRoTSendCommandPost(
192 const crow::Request& request,
193 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
194 const std::string& rotId)
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700195{
196 std::string command;
197 if (!redfish::json_util::readJsonAction(request, asyncResp->res, "Command",
198 command))
199 {
200 BMCWEB_LOG_DEBUG << "Missing property Command.";
201 redfish::messages::actionParameterMissing(asyncResp->res, "SendCommand",
202 "Command");
203 return;
204 }
205
206 resolveRoT(command, asyncResp, rotId, invokeRoTCommand);
207}
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -0700208
209inline void requestRoutes(App& app)
210{
211 BMCWEB_ROUTE(app, "/google/v1/")
Nan Zhou30aacdd2022-07-03 05:02:36 +0000212 .methods(boost::beast::http::verb::get)(handleGoogleV1Get);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700213
214 BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection")
215 .privileges({{"ConfigureManager"}})
Nan Zhou30aacdd2022-07-03 05:02:36 +0000216 .methods(boost::beast::http::verb::get)(handleRootOfTrustCollectionGet);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700217
218 BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection/<str>")
219 .privileges({{"ConfigureManager"}})
Nan Zhou30aacdd2022-07-03 05:02:36 +0000220 .methods(boost::beast::http::verb::get)(handleRootOfTrustGet);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700221
222 BMCWEB_ROUTE(
223 app,
224 "/google/v1/RootOfTrustCollection/<str>/Actions/RootOfTrust.SendCommand")
225 .privileges({{"ConfigureManager"}})
Nan Zhou30aacdd2022-07-03 05:02:36 +0000226 .methods(boost::beast::http::verb::post)(handleRoTSendCommandPost);
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -0700227}
228
229} // namespace google_api
230} // namespace crow