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