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