blob: 6db71c6efc359b3c93f17a11b8fb35381a2cd6bc [file] [log] [blame]
// 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