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