blob: d576a4a3cdae6a05920a1a67de19c1a75b39e943 [file] [log] [blame]
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef HAMMERD_HAMMER_UPDATER_H_
#define HAMMERD_HAMMER_UPDATER_H_
#include <memory>
#include <string>
#include <base/files/file_path.h>
#include <base/macros.h>
#include <metrics/metrics_library.h>
#include "hammerd/dbus_wrapper.h"
#include "hammerd/pair_utils.h"
#include "hammerd/update_fw.h"
namespace hammerd {
class HammerUpdater {
public:
// The result of the Run, RunLoop, RunOnce, .. methods.
enum class RunStatus {
kNoUpdate,
kFatalError,
kNeedReset,
kNeedJump,
kLostConnection,
kInvalidFirmware,
kTouchpadUpToDate,
kTouchpadMismatched,
kNeedLock,
};
enum class UpdateCondition {
kNever,
kMismatch,
kAlways,
kUnknown,
};
static UpdateCondition ToUpdateCondition(const std::string& s);
// The internal state used for RunOnce method. Each flag indicates a task, or
// an expectation at the next round. If the task or expectation is satisfied,
// then reset the flag.
struct TaskState {
// Flags to indicate whether the sections should be updated. Reset them
// after update is finished.
bool update_ro;
bool update_rw;
bool update_tp;
// Set the flag when the EC lacks entropy. Reset it after the entropy is
// injected successfully.
bool inject_entropy;
// Set the flag when we lock RW at the previous round.
bool post_rw_lock;
// Set the flag when we jump to RW at the previous round.
bool post_rw_jump;
TaskState()
: update_ro(false),
update_rw(false),
update_tp(false),
inject_entropy(false),
post_rw_lock(false),
post_rw_jump(false) {}
const std::string ToString();
};
HammerUpdater(const std::string& ec_image,
const std::string& touchpad_image,
const std::string& touchpad_product_id,
const std::string& touchpad_fw_ver,
uint16_t vendor_id,
uint16_t product_id,
const std::string& path,
bool at_boot,
UpdateCondition update_condition);
virtual ~HammerUpdater() = default;
// Handle the whole update process, including pre-processing, main update
// logic loop, and the post-processing.
virtual RunStatus Run();
// Handle the main update logic loop. For each round, it establishes the USB
// connection, calls RunOnce() method, and runs some actions according the
// returned status.
virtual RunStatus RunLoop();
// Handle the update logic from connecting to the EC to sending reset signal.
// There is only one USB connection during each RunOnce() method call.
virtual RunStatus RunOnce();
// The post processing after the RW section is up to date.
virtual RunStatus PostRWProcess();
// Update RO section if the device is in dogfood mode.
virtual RunStatus UpdateRO();
// Pair with the hammer device.
virtual RunStatus Pair();
// Update the touchpad firmware via the virtual address.
virtual RunStatus RunTouchpadUpdater();
// Extract product_id and firmware version.
static bool ParseTouchpadInfoFromFilename(const std::string& filename,
std::string* touchpad_product_id,
std::string* touchpad_fw_ver);
// Setter for inject_entropy control flag in TestState.
void SetInjectEntropyFlag(bool inject_entropy);
protected:
// Used in unittests to inject mock instance.
HammerUpdater(const std::string& ec_image,
const std::string& touchpad_image,
const std::string& touchpad_product_id,
const std::string& touchpad_fw_ver,
bool at_boot,
UpdateCondition update_condition,
std::unique_ptr<FirmwareUpdaterInterface> fw_updater,
std::unique_ptr<PairManagerInterface> pair_manager,
std::unique_ptr<DBusWrapperInterface> dbus_wrapper,
std::unique_ptr<MetricsLibraryInterface> metrics);
HammerUpdater(const HammerUpdater&) = delete;
HammerUpdater& operator=(const HammerUpdater&) = delete;
// Waits for hammer USB device ready. It is called after the whole updating
// process to prevent invoking hammerd infinitely.
void WaitUsbReady(HammerUpdater::RunStatus status);
// Sends DBus kBaseFirmwareNeedUpdateSignal to notify other processes that
// the RW section need to be updated.
// Note the update condition should be "never".
void NotifyNeedUpdate();
// Sends DBus kBaseFirmwareUpdateStartedSignal to notify other processes that
// the RW section will now be updated.
// Note the update condition should not be "never".
void NotifyUpdateStarted();
// Sends DBus signal to notify other processes that the RW section is updated
// successfully or failed.
// Note the update condition should not be "never".
void NotifyUpdateFinished(bool is_success);
template <typename HammerUpdaterType>
friend class HammerUpdaterTest;
private:
// The EC_image data to be updated.
const std::string ec_image_;
// The touchpad image data to be updated.
const std::string touchpad_image_;
// The touchpad firmware product id.
const std::string touchpad_product_id_;
// The touchpad firmware version.
const std::string touchpad_fw_ver_;
// Set this flag when hammerd is triggered at boot time.
const bool at_boot_;
// The update mode. Leave as non-const for unittesting purposes.
UpdateCondition update_condition_;
// The sysfs path of the USB device.
const base::FilePath base_path_;
// The internal state used for RunOnce method.
HammerUpdater::TaskState task_;
// The main firmware updater.
std::unique_ptr<FirmwareUpdaterInterface> fw_updater_;
// The pairing manager.
std::unique_ptr<PairManagerInterface> pair_manager_;
// The DBus wrapper is used to send signals to other processes.
std::unique_ptr<DBusWrapperInterface> dbus_wrapper_;
// When we send a DBus signal to notify that the update process is starting,
// we set this flag. After the whole process finishes, we will send another
// DBus signal to notify whether the process succeeded or failed, and the flag
// will be unset.
bool dbus_notified_;
// The UMA metrics object.
std::unique_ptr<MetricsLibraryInterface> metrics_;
// Utility functions for dealing with vendor and version strings.
std::string VersionString(TouchpadInfo info);
std::string VendorString(TouchpadInfo info);
// Helper function to update RW section.
HammerUpdater::RunStatus UpdateRW();
};
} // namespace hammerd
#endif // HAMMERD_HAMMER_UPDATER_H_