| // Copyright 2024 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "cli_parser.hpp" |
| |
| #include "parser.hpp" |
| #include "payload_update_common.hpp" |
| |
| #include <CLI/CLI.hpp> |
| |
| #include <unordered_map> |
| |
| namespace google::hoth::tools |
| { |
| bool CLIParser::parse(payload_update::Args& argsOut) |
| { |
| CLI::App app; |
| argsOut.command = payload_update::SubCommandType::kNop; |
| app.set_help_all_flag("--help-all", "Expand all help"); |
| app.add_option("--hoth_instance, -i", argsOut.hothId, "Hoth instance name"); |
| // Enforce accepting only one of the following sub-commands |
| app.require_subcommand(1); |
| auto* version = app.add_subcommand("version", "Get active payload version"); |
| version->add_flag("--next, -n", "Optional: Get next half version instead"); |
| auto* update = app.add_subcommand("update", "Update payload"); |
| update->add_option("filename", argsOut.payloadFilename, "Path to payload") |
| ->required() |
| ->check(CLI::ExistingFile); |
| std::unordered_map<std::string, payload_update::ResetMode> resetMap{ |
| {"never", payload_update::ResetMode::kNever}, |
| {"", payload_update::ResetMode::kNeeded}, |
| {"needed", payload_update::ResetMode::kNeeded}, |
| {"ignore_fail", payload_update::ResetMode::kIgnore}}; |
| argsOut.reset = payload_update::ResetMode::kNever; |
| update |
| ->add_option("--reset, -r", argsOut.reset, |
| "Put target in reset during update and pull target out of" |
| " reset after update") |
| ->transform(CLI::CheckedTransformer(resetMap)) |
| ->expected(0, 1); |
| argsOut.spsPassthrough = false; |
| update->add_flag("--sps_passthrough, -s", argsOut.spsPassthrough, |
| "Disable SPS passthrough during payload update and" |
| " re-enable it afterwards"); |
| std::unordered_map<std::string, payload_update::UpdateMode> updateMap{ |
| {"update_all", payload_update::UpdateMode::kUpdateAll}, |
| {"update_static_wp", |
| payload_update::UpdateMode::kUpdateStaticWPRegions}}; |
| argsOut.payloadUpdateMode = payload_update::UpdateMode::kUpdateAll; |
| update->add_option("--payloadUpdateMode, -m", argsOut.payloadUpdateMode, |
| "Erase entire partition for payload update or " |
| "just Static & WP sections") |
| ->transform(CLI::CheckedTransformer(updateMap)) |
| ->expected(0, 1); |
| try |
| { |
| app.parse(argc, argv); |
| } |
| catch (const CLI::ParseError& e) |
| { |
| // If cli app exit with non-zero error code, it's a real parse error. |
| // Otherwise, it's the '-h' help option and we should return gracefully. |
| return app.exit(e) == 0; |
| } |
| if (version->count()) |
| { |
| argsOut.command = payload_update::SubCommandType::kVersion; |
| argsOut.versionType = payload_update::VersionType::kActiveHalf; |
| if (version->count("--next") || version->count("-n")) |
| { |
| argsOut.versionType = payload_update::VersionType::kNextHalf; |
| } |
| } |
| else if (update->count()) |
| { |
| argsOut.command = payload_update::SubCommandType::kUpdate; |
| } |
| return true; |
| } |
| } // namespace google::hoth::tools |