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