| // 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 "payload_update_cli.hpp" |
| |
| #include "google3/host_commands.h" |
| |
| #include "dbus_interface.hpp" |
| #include "parser.hpp" |
| #include "payload_update_common.hpp" |
| |
| #include <iostream> |
| |
| namespace google::hoth::tools |
| { |
| namespace payload_update |
| { |
| bool PayloadUpdateCLI::doUpdate() |
| { |
| bool didReset = false; |
| |
| if (!args.hothId.empty()) |
| { |
| if (args.reset != ResetMode::kNever) |
| { |
| std::optional<bool> res; |
| try |
| { |
| res = dbus->getSpsPassthrough(args.hothId); |
| } |
| catch (const std::exception& e) |
| { |
| std::cerr << "Failed to get SPS passthrough status: " << e.what() |
| << '\n'; |
| } |
| if (!res && args.reset == ResetMode::kIgnore) |
| { |
| std::cerr << "Ignoring failed SPS passthrough status command" |
| << '\n'; |
| } |
| else if (res.value_or(true)) |
| { |
| std::cerr << "Target did not report SPS passthrough disabled. " |
| "Attempting reset" |
| << '\n'; |
| if (!dbus->setTargetResetOption(args.hothId, |
| EC_TARGET_RESET_OPTION_SET)) |
| { |
| std::cerr << "Failed to put target into reset" << '\n'; |
| return false; |
| } |
| didReset = true; |
| } |
| } |
| if (args.spsPassthrough && !dbus->setSpsPassthrough(args.hothId, false)) |
| { |
| std::cerr << "Failed to disable SPS passthrough" << '\n'; |
| return false; |
| } |
| } |
| if (args.payloadUpdateMode == UpdateMode::kUpdateStaticWPRegions) |
| { |
| if (!dbus->sendStaticWPPayloadAndVerify(args.hothId, |
| args.payloadFilename)) |
| { |
| std::cerr << "Failed to send payload (STATIC & WP) and verify" |
| << '\n'; |
| return false; |
| } |
| } |
| else |
| { |
| if (!dbus->eraseStagingArea(args.hothId)) |
| { |
| std::cerr << "Failed to erase staging area" << '\n'; |
| return false; |
| } |
| if (!dbus->sendPayloadAndVerify(args.hothId, args.payloadFilename)) |
| { |
| std::cerr << "Failed to send payload and verify" << '\n'; |
| return false; |
| } |
| } |
| if (!dbus->activatePayload(args.hothId)) |
| { |
| std::cerr << "Faild to activate payload" << '\n'; |
| return false; |
| } |
| |
| if (args.hothId.empty() && !dbus->expectConfirmPayload()) |
| { |
| std::cerr << "Failed to enable payload confirm" << '\n'; |
| return false; |
| } |
| |
| if (!args.hothId.empty()) |
| { |
| if (args.spsPassthrough && !dbus->setSpsPassthrough(args.hothId, true)) |
| { |
| std::cerr << "Failed to enable SPS passthrough" << '\n'; |
| return false; |
| } |
| if (didReset) |
| { |
| if (!dbus->setTargetResetOption(args.hothId, |
| EC_TARGET_RESET_OPTION_RELEASE)) |
| { |
| std::cerr << "Failed to release target from reset" << '\n'; |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| bool PayloadUpdateCLI::getOptions() |
| { |
| return parser->parse(args); |
| } |
| |
| bool PayloadUpdateCLI::execute() |
| { |
| switch (args.command) |
| { |
| using enum payload_update::SubCommandType; |
| case kVersion: |
| { |
| auto version = |
| dbus->getPayloadVersion(args.hothId, args.versionType); |
| if (version != std::nullopt) |
| { |
| std::cout << *version << '\n'; |
| return true; |
| } |
| return false; |
| } |
| case kUpdate: |
| return doUpdate(); |
| default: |
| break; |
| } |
| return true; |
| } |
| } // namespace payload_update |
| } // namespace google::hoth::tools |