1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3 // SPDX-FileCopyrightText: Copyright 2019 Intel Corporation 4 #pragma once 5 6 #include "app.hpp" 7 #include "query.hpp" 8 #include "registries.hpp" 9 #include "registries_selector.hpp" 10 11 #include <boost/url/format.hpp> 12 13 #include <array> 14 #include <format> 15 16 namespace redfish 17 { 18 19 inline void handleMessageRegistryFileCollectionGet( 20 crow::App& app, const crow::Request& req, 21 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 22 { 23 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 24 { 25 return; 26 } 27 // Collections don't include the static data added by SubRoute 28 // because it has a duplicate entry for members 29 30 asyncResp->res.jsonValue["@odata.type"] = 31 "#MessageRegistryFileCollection.MessageRegistryFileCollection"; 32 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Registries"; 33 asyncResp->res.jsonValue["Name"] = "MessageRegistryFile Collection"; 34 asyncResp->res.jsonValue["Description"] = 35 "Collection of MessageRegistryFiles"; 36 37 nlohmann::json& members = asyncResp->res.jsonValue["Members"]; 38 39 static constexpr const auto registryFiles = std::to_array( 40 {"Base", "TaskEvent", "ResourceEvent", "OpenBMC", "Telemetry", 41 "HeartbeatEvent"}); 42 43 for (const char* memberName : registryFiles) 44 { 45 nlohmann::json::object_t member; 46 member["@odata.id"] = 47 boost::urls::format("/redfish/v1/Registries/{}", memberName); 48 members.emplace_back(std::move(member)); 49 } 50 asyncResp->res.jsonValue["Members@odata.count"] = members.size(); 51 } 52 53 inline void requestRoutesMessageRegistryFileCollection(App& app) 54 { 55 /** 56 * Functions triggers appropriate requests on DBus 57 */ 58 BMCWEB_ROUTE(app, "/redfish/v1/Registries/") 59 .privileges(redfish::privileges::getMessageRegistryFileCollection) 60 .methods(boost::beast::http::verb::get)(std::bind_front( 61 handleMessageRegistryFileCollectionGet, std::ref(app))); 62 } 63 64 inline void handleMessageRoutesMessageRegistryFileGet( 65 crow::App& app, const crow::Request& req, 66 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 67 const std::string& registry) 68 { 69 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 70 { 71 return; 72 } 73 std::string dmtf = "DMTF "; 74 std::optional<registries::HeaderAndUrl> headerAndUrl = 75 registries::getRegistryHeaderAndUrlFromPrefix(registry); 76 77 if (!headerAndUrl) 78 { 79 messages::resourceNotFound(asyncResp->res, "MessageRegistryFile", 80 registry); 81 return; 82 } 83 if (registry == "OpenBMC") 84 { 85 dmtf.clear(); 86 } 87 const registries::Header& header = headerAndUrl->header; 88 const char* url = headerAndUrl->url; 89 90 asyncResp->res.jsonValue["@odata.id"] = 91 boost::urls::format("/redfish/v1/Registries/{}", registry); 92 asyncResp->res.jsonValue["@odata.type"] = 93 "#MessageRegistryFile.v1_1_0.MessageRegistryFile"; 94 asyncResp->res.jsonValue["Name"] = registry + " Message Registry File"; 95 asyncResp->res.jsonValue["Description"] = 96 dmtf + registry + " Message Registry File Location"; 97 asyncResp->res.jsonValue["Id"] = header.registryPrefix; 98 asyncResp->res.jsonValue["Registry"] = 99 std::format("{}.{}.{}", header.registryPrefix, header.versionMajor, 100 header.versionMinor); 101 nlohmann::json::array_t languages; 102 languages.emplace_back(header.language); 103 asyncResp->res.jsonValue["Languages@odata.count"] = languages.size(); 104 asyncResp->res.jsonValue["Languages"] = std::move(languages); 105 nlohmann::json::array_t locationMembers; 106 nlohmann::json::object_t location; 107 location["Language"] = header.language; 108 location["Uri"] = "/redfish/v1/Registries/" + registry + "/" + registry; 109 110 if (url != nullptr) 111 { 112 location["PublicationUri"] = url; 113 } 114 locationMembers.emplace_back(std::move(location)); 115 asyncResp->res.jsonValue["Location@odata.count"] = locationMembers.size(); 116 asyncResp->res.jsonValue["Location"] = std::move(locationMembers); 117 } 118 119 inline void requestRoutesMessageRegistryFile(App& app) 120 { 121 BMCWEB_ROUTE(app, "/redfish/v1/Registries/<str>/") 122 .privileges(redfish::privileges::getMessageRegistryFile) 123 .methods(boost::beast::http::verb::get)(std::bind_front( 124 handleMessageRoutesMessageRegistryFileGet, std::ref(app))); 125 } 126 127 inline void handleMessageRegistryGet( 128 crow::App& app, const crow::Request& req, 129 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 130 const std::string& registry, const std::string& registryMatch) 131 132 { 133 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 134 { 135 return; 136 } 137 138 std::optional<registries::HeaderAndUrl> headerAndUrl = 139 registries::getRegistryHeaderAndUrlFromPrefix(registry); 140 if (!headerAndUrl) 141 { 142 messages::resourceNotFound(asyncResp->res, "MessageRegistryFile", 143 registry); 144 return; 145 } 146 147 const registries::Header& header = headerAndUrl->header; 148 if (registry != registryMatch) 149 { 150 messages::resourceNotFound(asyncResp->res, header.type, registryMatch); 151 return; 152 } 153 154 asyncResp->res.jsonValue["@Redfish.Copyright"] = header.copyright; 155 asyncResp->res.jsonValue["@odata.type"] = header.type; 156 asyncResp->res.jsonValue["Id"] = 157 std::format("{}.{}.{}.{}", header.registryPrefix, header.versionMajor, 158 header.versionMinor, header.versionPatch); 159 asyncResp->res.jsonValue["Name"] = header.name; 160 asyncResp->res.jsonValue["Language"] = header.language; 161 asyncResp->res.jsonValue["Description"] = header.description; 162 asyncResp->res.jsonValue["RegistryPrefix"] = header.registryPrefix; 163 asyncResp->res.jsonValue["RegistryVersion"] = 164 std::format("{}.{}.{}", header.versionMajor, header.versionMinor, 165 header.versionPatch); 166 asyncResp->res.jsonValue["OwningEntity"] = header.owningEntity; 167 168 nlohmann::json& messageObj = asyncResp->res.jsonValue["Messages"]; 169 170 // Go through the Message Registry and populate each Message 171 const std::span<const registries::MessageEntry> registryEntries = 172 registries::getRegistryFromPrefix(registry); 173 174 for (const registries::MessageEntry& message : registryEntries) 175 { 176 nlohmann::json& obj = messageObj[message.first]; 177 obj["Description"] = message.second.description; 178 obj["Message"] = message.second.message; 179 obj["Severity"] = message.second.messageSeverity; 180 obj["MessageSeverity"] = message.second.messageSeverity; 181 obj["NumberOfArgs"] = message.second.numberOfArgs; 182 obj["Resolution"] = message.second.resolution; 183 if (message.second.numberOfArgs > 0) 184 { 185 nlohmann::json& messageParamArray = obj["ParamTypes"]; 186 messageParamArray = nlohmann::json::array(); 187 for (const char* str : message.second.paramTypes) 188 { 189 if (str == nullptr) 190 { 191 break; 192 } 193 messageParamArray.push_back(str); 194 } 195 } 196 } 197 } 198 199 inline void requestRoutesMessageRegistry(App& app) 200 { 201 BMCWEB_ROUTE(app, "/redfish/v1/Registries/<str>/<str>/") 202 .privileges(redfish::privileges::getMessageRegistryFile) 203 .methods(boost::beast::http::verb::get)( 204 std::bind_front(handleMessageRegistryGet, std::ref(app))); 205 } 206 } // namespace redfish 207