New monitor eeprom fill GDB command

This commit is contained in:
Nav
2022-12-10 19:22:53 +00:00
parent 8f48a30fa3
commit ffe4f5bfc5
5 changed files with 171 additions and 0 deletions

View File

@@ -0,0 +1,110 @@
#include "EepromFill.hpp"
#include <QByteArray>
#include <algorithm>
#include "src/DebugServer/Gdb/ResponsePackets/ResponsePacket.hpp"
#include "src/DebugServer/Gdb/ResponsePackets/ErrorResponsePacket.hpp"
#include "src/DebugServer/Gdb/Exceptions/InvalidCommandOption.hpp"
#include "src/Exceptions/Exception.hpp"
#include "src/Logger/Logger.hpp"
namespace Bloom::DebugServer::Gdb::CommandPackets
{
using TargetController::TargetControllerConsole;
using ResponsePackets::ResponsePacket;
using ResponsePackets::ErrorResponsePacket;
using Bloom::Exceptions::Exception;
using Exceptions::InvalidCommandOption;
EepromFill::EepromFill(Monitor&& monitorPacket)
: Monitor(std::move(monitorPacket))
{
const auto fillValueOptionIt = this->commandOptions.find("value");
if (fillValueOptionIt == this->commandOptions.end() || !fillValueOptionIt->second.has_value()) {
return;
}
const auto fillValueByteArray = QByteArray::fromHex(QByteArray::fromStdString(*fillValueOptionIt->second));
this->fillValue = Targets::TargetMemoryBuffer(fillValueByteArray.begin(), fillValueByteArray.end());
}
void EepromFill::handle(DebugSession& debugSession, TargetControllerConsole& targetControllerConsole) {
Logger::debug("Handling EepromFill packet");
try {
const auto& targetDescriptor = debugSession.gdbTargetDescriptor.targetDescriptor;
const auto eepromDescriptorIt = targetDescriptor.memoryDescriptorsByType.find(
Targets::TargetMemoryType::EEPROM
);
if (eepromDescriptorIt == targetDescriptor.memoryDescriptorsByType.end()) {
throw Exception("Target has no EEPROM");
}
const auto& eepromDescriptor = eepromDescriptorIt->second;
const auto eepromSize = eepromDescriptor.size();
const auto fillValueSize = this->fillValue.size();
if (fillValueSize == 0) {
throw InvalidCommandOption("Fill value required");
}
if (fillValueSize > eepromSize) {
throw InvalidCommandOption(
"Fill value size ("+ std::to_string(fillValueSize) + " bytes) exceeds EEPROM size ("
+ std::to_string(eepromSize) + " bytes)"
);
}
if ((eepromSize % fillValueSize) != 0) {
Logger::warning(
"The fill value size (" + std::to_string(fillValueSize) + " bytes) is not a multiple of the EEPROM "
"size (" + std::to_string(eepromSize) + " bytes) - the fill value will be truncated"
);
}
Logger::warning("Filling " + std::to_string(eepromSize) + " bytes of EEPROM");
auto data = Targets::TargetMemoryBuffer();
data.reserve(eepromSize);
// Repeat this->fillValue until we've filled `data`
while (data.size() < eepromSize) {
data.insert(
data.end(),
this->fillValue.begin(),
this->fillValue.begin() + static_cast<std::int32_t>(
std::min(fillValueSize, (eepromSize - data.size()))
)
);
}
const auto hexValues = Packet::toHex(data);
Logger::debug("Filling EEPROM with values: " + hexValues);
targetControllerConsole.writeMemory(
Targets::TargetMemoryType::EEPROM,
eepromDescriptor.addressRange.startAddress,
std::move(data)
);
debugSession.connection.writePacket(ResponsePacket(Packet::toHex(
"Filled " + std::to_string(eepromSize) + " bytes of EEPROM, with values: " + hexValues + "\n"
)));
} catch (const InvalidCommandOption& exception) {
Logger::error(exception.getMessage());
debugSession.connection.writePacket(ResponsePacket(Packet::toHex(exception.getMessage() + "\n")));
} catch (const Exception& exception) {
Logger::error("Failed to fill EEPROM - " + exception.getMessage());
debugSession.connection.writePacket(ErrorResponsePacket());
}
}
}

View File

@@ -0,0 +1,29 @@
#pragma once
#include <cstdint>
#include "Monitor.hpp"
#include "src/Targets/TargetMemory.hpp"
namespace Bloom::DebugServer::Gdb::CommandPackets
{
/**
* The EepromFill class implements a structure for the "monitor eeprom fill" GDB command.
*
* This command fills the target's EEPROM with the given value.
*/
class EepromFill: public Monitor
{
public:
explicit EepromFill(Monitor&& monitorPacket);
void handle(
DebugSession& debugSession,
TargetController::TargetControllerConsole& targetControllerConsole
) override;
private:
Targets::TargetMemoryBuffer fillValue;
};
}