xref: /openbmc/phosphor-ipmi-flash/bmc/firmware-handler/firmware_handlers_builder.cpp (revision 42a44c281cce08be0ca6251955f4fb73d30c8ced)
1c893f43dSJason Ling /*
2c893f43dSJason Ling  * Copyright 2019 Google Inc.
3c893f43dSJason Ling  *
4c893f43dSJason Ling  * Licensed under the Apache License, Version 2.0 (the "License");
5c893f43dSJason Ling  * you may not use this file except in compliance with the License.
6c893f43dSJason Ling  * You may obtain a copy of the License at
7c893f43dSJason Ling  *
8c893f43dSJason Ling  *     http://www.apache.org/licenses/LICENSE-2.0
9c893f43dSJason Ling  *
10c893f43dSJason Ling  * Unless required by applicable law or agreed to in writing, software
11c893f43dSJason Ling  * distributed under the License is distributed on an "AS IS" BASIS,
12c893f43dSJason Ling  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c893f43dSJason Ling  * See the License for the specific language governing permissions and
14c893f43dSJason Ling  * limitations under the License.
15c893f43dSJason Ling  */
16c893f43dSJason Ling #include "firmware_handlers_builder.hpp"
17c893f43dSJason Ling 
18c893f43dSJason Ling #include "file_handler.hpp"
19c893f43dSJason Ling #include "fs.hpp"
20bec23189SWilliam A. Kennington III #include "general_systemd.hpp"
21c893f43dSJason Ling #include "skip_action.hpp"
22c893f43dSJason Ling 
23c893f43dSJason Ling #include <nlohmann/json.hpp>
24c893f43dSJason Ling 
25c893f43dSJason Ling #include <algorithm>
26c893f43dSJason Ling #include <cstdio>
27c893f43dSJason Ling #include <exception>
28c893f43dSJason Ling #include <fstream>
29c893f43dSJason Ling #include <regex>
30c893f43dSJason Ling #include <string>
31c893f43dSJason Ling #include <vector>
32c893f43dSJason Ling 
33c893f43dSJason Ling namespace ipmi_flash
34c893f43dSJason Ling {
35c893f43dSJason Ling std::vector<HandlerConfig<ActionPack>>
buildHandlerFromJson(const nlohmann::json & data)36c893f43dSJason Ling     FirmwareHandlersBuilder::buildHandlerFromJson(const nlohmann::json& data)
37c893f43dSJason Ling {
38c893f43dSJason Ling     std::vector<HandlerConfig<ActionPack>> handlers;
39c893f43dSJason Ling 
40c893f43dSJason Ling     for (const auto& item : data)
41c893f43dSJason Ling     {
42c893f43dSJason Ling         try
43c893f43dSJason Ling         {
44c893f43dSJason Ling             HandlerConfig<ActionPack> output;
45c893f43dSJason Ling 
46c893f43dSJason Ling             /* at() throws an exception when the key is not present. */
47c893f43dSJason Ling             item.at("blob").get_to(output.blobId);
48c893f43dSJason Ling 
49c893f43dSJason Ling             /* name must be: /flash/... */
50c893f43dSJason Ling             if (!std::regex_match(output.blobId, std::regex("^\\/flash\\/.+")))
51c893f43dSJason Ling             {
52*42a44c28SPatrick Williams                 throw std::runtime_error(
53*42a44c28SPatrick Williams                     "Invalid blob name: '" + output.blobId +
54c893f43dSJason Ling                     "' must start with /flash/");
55c893f43dSJason Ling             }
56c893f43dSJason Ling 
57c893f43dSJason Ling             /* handler is required. */
58c893f43dSJason Ling             const auto& h = item.at("handler");
59c893f43dSJason Ling             const std::string handlerType = h.at("type");
60c893f43dSJason Ling             if (handlerType == "file")
61c893f43dSJason Ling             {
62c893f43dSJason Ling                 const auto& path = h.at("path");
63c893f43dSJason Ling                 output.handler = std::make_unique<FileHandler>(path);
64c893f43dSJason Ling             }
65c893f43dSJason Ling             else
66c893f43dSJason Ling             {
67*42a44c28SPatrick Williams                 throw std::runtime_error(
68*42a44c28SPatrick Williams                     "Invalid handler type: " + handlerType);
69c893f43dSJason Ling             }
70c893f43dSJason Ling 
71c893f43dSJason Ling             /* actions are required (presently). */
72c893f43dSJason Ling             const auto& a = item.at("actions");
73c893f43dSJason Ling             std::unique_ptr<ActionPack> pack = std::make_unique<ActionPack>();
74c893f43dSJason Ling 
75c893f43dSJason Ling             /* to make an action optional, assign type "skip" */
76c893f43dSJason Ling             const auto& prep = a.at("preparation");
77c893f43dSJason Ling             const std::string prepareType = prep.at("type");
78c893f43dSJason Ling             if (prepareType == "systemd")
79c893f43dSJason Ling             {
80c893f43dSJason Ling                 pack->preparation = std::move(buildSystemd(prep));
81c893f43dSJason Ling             }
82c893f43dSJason Ling             else if (prepareType == "skip")
83c893f43dSJason Ling             {
84c893f43dSJason Ling                 pack->preparation = SkipAction::CreateSkipAction();
85c893f43dSJason Ling             }
86c893f43dSJason Ling             else
87c893f43dSJason Ling             {
88*42a44c28SPatrick Williams                 throw std::runtime_error(
89*42a44c28SPatrick Williams                     "Invalid preparation type: " + prepareType);
90c893f43dSJason Ling             }
91c893f43dSJason Ling 
92c893f43dSJason Ling             const auto& verify = a.at("verification");
93c893f43dSJason Ling             const std::string verifyType = verify.at("type");
94c893f43dSJason Ling             if (verifyType == "fileSystemdVerify")
95c893f43dSJason Ling             {
96c893f43dSJason Ling                 pack->verification = std::move(buildFileSystemd(verify));
97c893f43dSJason Ling             }
98c893f43dSJason Ling             else if (verifyType == "systemd")
99c893f43dSJason Ling             {
100c893f43dSJason Ling                 pack->verification = std::move(buildSystemd(verify));
101c893f43dSJason Ling             }
102c893f43dSJason Ling             else if (verifyType == "skip")
103c893f43dSJason Ling             {
104c893f43dSJason Ling                 pack->verification = SkipAction::CreateSkipAction();
105c893f43dSJason Ling             }
106c893f43dSJason Ling             else
107c893f43dSJason Ling             {
108*42a44c28SPatrick Williams                 throw std::runtime_error(
109*42a44c28SPatrick Williams                     "Invalid verification type:" + verifyType);
110c893f43dSJason Ling             }
111c893f43dSJason Ling 
112c893f43dSJason Ling             const auto& update = a.at("update");
113c893f43dSJason Ling             const std::string updateType = update.at("type");
114c893f43dSJason Ling             if (updateType == "reboot")
115c893f43dSJason Ling             {
116c893f43dSJason Ling                 pack->update = SystemdNoFile::CreateSystemdNoFile(
117c893f43dSJason Ling                     sdbusplus::bus::new_default(), "reboot.target",
118c893f43dSJason Ling                     "replace-irreversibly");
119c893f43dSJason Ling             }
120c893f43dSJason Ling             else if (updateType == "fileSystemdUpdate")
121c893f43dSJason Ling             {
122c893f43dSJason Ling                 pack->update = std::move(buildFileSystemd(update));
123c893f43dSJason Ling             }
124c893f43dSJason Ling             else if (updateType == "systemd")
125c893f43dSJason Ling             {
126c893f43dSJason Ling                 pack->update = std::move(buildSystemd(update));
127c893f43dSJason Ling             }
128c893f43dSJason Ling             else if (updateType == "skip")
129c893f43dSJason Ling             {
130c893f43dSJason Ling                 pack->update = SkipAction::CreateSkipAction();
131c893f43dSJason Ling             }
132c893f43dSJason Ling             else
133c893f43dSJason Ling             {
134c893f43dSJason Ling                 throw std::runtime_error("Invalid update type: " + updateType);
135c893f43dSJason Ling             }
136c893f43dSJason Ling 
137c893f43dSJason Ling             output.actions = std::move(pack);
138c893f43dSJason Ling             handlers.push_back(std::move(output));
139c893f43dSJason Ling         }
140c893f43dSJason Ling         catch (const std::exception& e)
141c893f43dSJason Ling         {
142c893f43dSJason Ling             /* TODO: Once phosphor-logging supports unit-test injection, fix
143c893f43dSJason Ling              * this to log.
144c893f43dSJason Ling              */
145c893f43dSJason Ling             std::fprintf(stderr,
146c893f43dSJason Ling                          "Excepted building HandlerConfig from json: %s\n",
147c893f43dSJason Ling                          e.what());
148c893f43dSJason Ling         }
149c893f43dSJason Ling     }
150c893f43dSJason Ling 
151c893f43dSJason Ling     return handlers;
152c893f43dSJason Ling }
153c893f43dSJason Ling } // namespace ipmi_flash
154