blob: e7734e66504237df483942c817ffcd43b458976a [file] [log] [blame]
// Copyright 2021 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.
/*
* Fake device for HPS testing.
*/
#ifndef HPS_HAL_FAKE_DEV_H_
#define HPS_HAL_FAKE_DEV_H_
#include <map>
#include <memory>
#include "hps/dev.h"
#include "hps/hps_reg.h"
namespace hps {
/*
* FakeDev is an class that when started, spawns a thread to
* asynchronously process register reads/writes and memory writes to
* simulate the HPS hardware.
* A separate thread is used to simulate the latency and concurrency of
* the real device.
*
* A set of flags defines behaviour of the device (such as forced errors etc.).
*/
class FakeDev : public DevInterface {
public:
FakeDev() { this->SetStage(Stage::kStage0); }
// Flags for controlling behaviour. Multiple flags can be set,
// controlling how the fake responds under test conditions.
enum class Flags {
// Set MCU RW not verified status bit.
kStage1NotVerified = 1,
// Set SPI flash not verified status bit.
kSpiNotVerified = 2,
// Set WP bit as off.
kWpOff = 3,
// Fail any memory writes.
kMemFail = 4,
// If MCU download occurs, reset the RW not-verified flag.
kResetApplVerification = 5,
// If SPI download occurs, reset the SPI not-verified flag.
kResetSpiVerification = 6,
// When a RW download occurs, increment the firmware version number.
kIncrementVersion = 7,
// Set MCU flash ECC error bit when launching stage1.
kFlashEccError = 8,
};
bool ReadDevice(uint8_t cmd, uint8_t* data, size_t len) override;
bool WriteDevice(uint8_t cmd, const uint8_t* data, size_t len) override;
size_t BlockSizeBytes() override { return this->block_size_b_; }
void SkipBoot() { this->SetStage(Stage::kAppl); }
void Set(Flags f) {
this->flags_ |= static_cast<uint16_t>(1 << static_cast<int>(f));
}
void Clear(Flags f) {
this->flags_ &= ~static_cast<uint16_t>(1 << static_cast<int>(f));
}
void SetVersion(uint32_t version) { this->firmware_version_ = version; }
void SetBlockSizeBytes(size_t sz) { this->block_size_b_ = sz; }
void SetF0Result(int8_t result, bool valid) {
this->f0_result_ =
(valid ? hps::RFeat::kValid : 0) | static_cast<uint8_t>(result);
}
void SetF1Result(int8_t result, bool valid) {
this->f1_result_ =
(valid ? hps::RFeat::kValid : 0) | static_cast<uint8_t>(result);
}
size_t GetBankLen(hps::HpsBank bank);
// Return a DevInterface accessing the simulator.
std::unique_ptr<DevInterface> CreateDevInterface();
private:
uint16_t ReadRegister(HpsReg r);
void WriteRegister(HpsReg r, uint16_t v);
bool WriteMemory(HpsBank bank, const uint8_t* mem, size_t len);
bool Flag(Flags f) {
return (this->flags_ & (1 << static_cast<int>(f))) != 0;
}
// Current stage (phase) of the device.
// The device behaves differently in different stages.
enum class Stage {
kStage0,
kStage1,
kAppl,
};
void SetStage(Stage s);
std::map<HpsBank, size_t> bank_len_; // Count of writes to banks.
std::map<HpsBank, bool> bank_erased_; // Whether bank has been erased
Stage stage_; // Current stage of the device
RError fault_ = RError::kNone; // Fault (error) value
uint16_t feature_on_ = 0; // Enabled features.
uint16_t bank_ = 0; // Current memory bank readiness
uint16_t flags_ = 0; // Behaviour flags
uint32_t firmware_version_ = 0; // Firmware version
size_t block_size_b_ = 256; // Write block size.
uint16_t f0_result_ = 0; // Register value for feature 0
uint16_t f1_result_ = 0; // Register value for feature 1
};
} // namespace hps
#endif // HPS_HAL_FAKE_DEV_H_