blob: 7d48845714af3758377231fe93455a0a83f76b77 [file] [log] [blame]
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -07001#pragma once
2
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08003#include "app.hpp"
4#include "async_resp.hpp"
5#include "dbus_utility.hpp"
6#include "error_messages.hpp"
7#include "utils/collection.hpp"
8#include "utils/hex_utils.hpp"
9#include "utils/json_utils.hpp"
10
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -070011#include <nlohmann/json.hpp>
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070012
George Liu7a1dbc42022-12-07 16:03:22 +080013#include <array>
14#include <string_view>
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070015#include <vector>
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -070016
17namespace crow
18{
19namespace google_api
20{
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070021
Nan Zhou30aacdd2022-07-03 05:02:36 +000022inline void
23 handleGoogleV1Get(const crow::Request& /*req*/,
24 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070025{
26 asyncResp->res.jsonValue["@odata.type"] =
27 "#GoogleServiceRoot.v1_0_0.GoogleServiceRoot";
28 asyncResp->res.jsonValue["@odata.id"] = "/google/v1";
29 asyncResp->res.jsonValue["Id"] = "Google Rest RootService";
30 asyncResp->res.jsonValue["Name"] = "Google Service Root";
31 asyncResp->res.jsonValue["Version"] = "1.0.0";
32 asyncResp->res.jsonValue["RootOfTrustCollection"]["@odata.id"] =
Nan Zhoucd027592022-07-03 05:18:29 +000033 "/google/v1/RootOfTrustCollection";
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070034}
35
Nan Zhou30aacdd2022-07-03 05:02:36 +000036inline void handleRootOfTrustCollectionGet(
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070037 const crow::Request& /*req*/,
38 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
39{
Nan Zhoucd027592022-07-03 05:18:29 +000040 asyncResp->res.jsonValue["@odata.id"] = "/google/v1/RootOfTrustCollection";
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070041 asyncResp->res.jsonValue["@odata.type"] =
42 "#RootOfTrustCollection.RootOfTrustCollection";
George Liu7a1dbc42022-12-07 16:03:22 +080043 const std::array<std::string_view, 1> interfaces{
44 "xyz.openbmc_project.Control.Hoth"};
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070045 redfish::collection_util::getCollectionMembers(
Willy Tuae9031f2022-09-27 05:48:07 +000046 asyncResp, boost::urls::url("/google/v1/RootOfTrustCollection"),
George Liu7a1dbc42022-12-07 16:03:22 +080047 interfaces, "/xyz/openbmc_project");
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070048}
49
50// Helper struct to identify a resolved D-Bus object interface
51struct ResolvedEntity
52{
53 std::string id;
54 std::string service;
55 std::string object;
Nan Zhou16a55352022-07-03 05:06:08 +000056 std::string interface;
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070057};
58
59using ResolvedEntityHandler = std::function<void(
60 const std::string&, const std::shared_ptr<bmcweb::AsyncResp>&,
61 const ResolvedEntity&)>;
62
Nan Zhou30aacdd2022-07-03 05:02:36 +000063inline void hothGetSubtreeCallback(
64 const std::string& command,
65 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
66 const std::string& rotId, const ResolvedEntityHandler& entityHandler,
67 const boost::system::error_code ec,
68 const dbus::utility::MapperGetSubTreeResponse& subtree)
69{
70 if (ec)
71 {
72 redfish::messages::internalError(asyncResp->res);
73 return;
74 }
Nan Zhou5600f022022-07-03 16:22:38 +000075 for (const auto& [path, services] : subtree)
Nan Zhou30aacdd2022-07-03 05:02:36 +000076 {
Nan Zhou5600f022022-07-03 16:22:38 +000077 sdbusplus::message::object_path objPath(path);
78 if (objPath.filename() != rotId || services.empty())
Nan Zhou30aacdd2022-07-03 05:02:36 +000079 {
80 continue;
81 }
82
Nan Zhoucd027592022-07-03 05:18:29 +000083 ResolvedEntity resolvedEntity = {
84 .id = rotId,
Nan Zhou5600f022022-07-03 16:22:38 +000085 .service = services[0].first,
86 .object = path,
Nan Zhoucd027592022-07-03 05:18:29 +000087 .interface = "xyz.openbmc_project.Control.Hoth"};
Nan Zhou30aacdd2022-07-03 05:02:36 +000088 entityHandler(command, asyncResp, resolvedEntity);
89 return;
90 }
91
92 // Couldn't find an object with that name. return an error
Jiaqing Zhaod8a5d5d2022-08-05 16:21:51 +080093 redfish::messages::resourceNotFound(asyncResp->res, "RootOfTrust", rotId);
Nan Zhou30aacdd2022-07-03 05:02:36 +000094}
95
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -070096inline void resolveRoT(const std::string& command,
97 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
98 const std::string& rotId,
99 ResolvedEntityHandler&& entityHandler)
100{
Nan Zhou30aacdd2022-07-03 05:02:36 +0000101
George Liu7a1dbc42022-12-07 16:03:22 +0800102 constexpr std::array<std::string_view, 1> hothIfaces = {
Nan Zhoucd027592022-07-03 05:18:29 +0000103 "xyz.openbmc_project.Control.Hoth"};
Nan Zhou30aacdd2022-07-03 05:02:36 +0000104 crow::connections::systemBus->async_method_call(
Ed Tanous002d39b2022-05-31 08:59:27 -0700105 [command, asyncResp, rotId,
106 entityHandler{std::forward<ResolvedEntityHandler>(entityHandler)}](
107 const boost::system::error_code ec,
108 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Nan Zhou30aacdd2022-07-03 05:02:36 +0000109 hothGetSubtreeCallback(command, asyncResp, rotId, entityHandler, ec,
110 subtree);
111 },
112 "xyz.openbmc_project.ObjectMapper",
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700113 "/xyz/openbmc_project/object_mapper",
Nan Zhoucd027592022-07-03 05:18:29 +0000114 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
115 "/xyz/openbmc_project",
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700116 /*depth=*/0, hothIfaces);
117}
118
119inline void populateRootOfTrustEntity(
120 const std::string& /*unused*/,
121 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
122 const ResolvedEntity& resolvedEntity)
123{
124 asyncResp->res.jsonValue["@odata.type"] = "#RootOfTrust.v1_0_0.RootOfTrust";
125 asyncResp->res.jsonValue["@odata.id"] =
126 "/google/v1/RootOfTrustCollection/" + resolvedEntity.id;
127
128 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
129 asyncResp->res.jsonValue["Id"] = resolvedEntity.id;
130 // Need to fix this later to a stabler property.
131 asyncResp->res.jsonValue["Name"] = resolvedEntity.id;
132 asyncResp->res.jsonValue["Description"] = "Google Root Of Trust";
133 asyncResp->res.jsonValue["Actions"]["#RootOfTrust.SendCommand"]["target"] =
134 "/google/v1/RootOfTrustCollection/" + resolvedEntity.id +
135 "/Actions/RootOfTrust.SendCommand";
136
137 asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
138 resolvedEntity.id;
139 asyncResp->res.jsonValue["Location"]["PartLocation"]["LocationType"] =
140 "Embedded";
141}
142
Nan Zhou30aacdd2022-07-03 05:02:36 +0000143inline void
144 handleRootOfTrustGet(const crow::Request& /*req*/,
145 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
146 const std::string& param)
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700147{
Nan Zhou30aacdd2022-07-03 05:02:36 +0000148 std::string emptyCommand;
149 resolveRoT(emptyCommand, asyncResp, param, populateRootOfTrustEntity);
150}
151
152inline void
153 invocationCallback(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
154 const boost::system::error_code ec,
155 const std::vector<uint8_t>& responseBytes)
156{
157 if (ec)
158 {
159 BMCWEB_LOG_ERROR << "RootOfTrust.Actions.SendCommand failed: "
160 << ec.message();
161 redfish::messages::internalError(asyncResp->res);
162 return;
163 }
164
165 asyncResp->res.jsonValue["CommandResponse"] =
166 bytesToHexString(responseBytes);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700167}
168
169inline void
170 invokeRoTCommand(const std::string& command,
171 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
172 const ResolvedEntity& resolvedEntity)
173{
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700174 std::vector<uint8_t> bytes = hexStringToBytes(command);
175 if (bytes.empty())
176 {
177 BMCWEB_LOG_DEBUG << "Invalid command: " << command;
178 redfish::messages::actionParameterValueTypeError(command, "Command",
179 "SendCommand");
180 return;
181 }
182
183 crow::connections::systemBus->async_method_call(
Nan Zhou30aacdd2022-07-03 05:02:36 +0000184 [asyncResp{asyncResp}](const boost::system::error_code ec,
185 const std::vector<uint8_t>& responseBytes) {
186 invocationCallback(asyncResp, ec, responseBytes);
187 },
188 resolvedEntity.service, resolvedEntity.object, resolvedEntity.interface,
189 "SendHostCommand", bytes);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700190}
191
Nan Zhou30aacdd2022-07-03 05:02:36 +0000192inline void handleRoTSendCommandPost(
193 const crow::Request& request,
194 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
195 const std::string& rotId)
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700196{
197 std::string command;
198 if (!redfish::json_util::readJsonAction(request, asyncResp->res, "Command",
199 command))
200 {
201 BMCWEB_LOG_DEBUG << "Missing property Command.";
202 redfish::messages::actionParameterMissing(asyncResp->res, "SendCommand",
203 "Command");
204 return;
205 }
206
207 resolveRoT(command, asyncResp, rotId, invokeRoTCommand);
208}
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -0700209
210inline void requestRoutes(App& app)
211{
212 BMCWEB_ROUTE(app, "/google/v1/")
Nan Zhou30aacdd2022-07-03 05:02:36 +0000213 .methods(boost::beast::http::verb::get)(handleGoogleV1Get);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700214
215 BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection")
216 .privileges({{"ConfigureManager"}})
Nan Zhou30aacdd2022-07-03 05:02:36 +0000217 .methods(boost::beast::http::verb::get)(handleRootOfTrustCollectionGet);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700218
219 BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection/<str>")
220 .privileges({{"ConfigureManager"}})
Nan Zhou30aacdd2022-07-03 05:02:36 +0000221 .methods(boost::beast::http::verb::get)(handleRootOfTrustGet);
Vidya Satyamsetti4cee35e2022-04-21 14:53:44 -0700222
223 BMCWEB_ROUTE(
224 app,
225 "/google/v1/RootOfTrustCollection/<str>/Actions/RootOfTrust.SendCommand")
226 .privileges({{"ConfigureManager"}})
Nan Zhou30aacdd2022-07-03 05:02:36 +0000227 .methods(boost::beast::http::verb::post)(handleRoTSendCommandPost);
Feras Aldahlawi735ef6d2021-03-19 14:01:46 -0700228}
229
230} // namespace google_api
231} // namespace crow