Apply formatting rules.
This commit is contained in:
parent
3d44e39c32
commit
d40724c096
|
@ -30,8 +30,8 @@
|
|||
|
||||
|
||||
uint32_t AnalysisState::getAddressOffset(uint8_t offsetEntry) const {
|
||||
if(offsetEntry == 0){
|
||||
if (offsetEntry == 0) {
|
||||
return 0;
|
||||
}
|
||||
return getRegister((uint32_t)KnownRegisters::BSM_ADDR_OFFSET_0 + offsetEntry);
|
||||
return getRegister((uint32_t) KnownRegisters::BSM_ADDR_OFFSET_0 + offsetEntry);
|
||||
}
|
|
@ -32,7 +32,7 @@
|
|||
#include <unordered_map>
|
||||
#include "SmallFirmwareFormat.h"
|
||||
|
||||
class AnalysisState{
|
||||
class AnalysisState {
|
||||
public:
|
||||
std::unordered_map<uint32_t, uint32_t> memory;
|
||||
uint32_t previous;
|
||||
|
@ -41,22 +41,25 @@ public:
|
|||
SmallFirmwareFormat pciSPICOFirmware;
|
||||
SmallFirmwareFormat pciSerDesFirmware;
|
||||
|
||||
AnalysisState(uint32_t initial) : current(initial), previous(0){
|
||||
|
||||
}
|
||||
AnalysisState(const AnalysisState& oldState) : current(oldState.current), previous(oldState.previous), memory(oldState.memory), pciSPICOFirmware(oldState.pciSPICOFirmware), pciSerDesFirmware(oldState.pciSerDesFirmware){
|
||||
AnalysisState(uint32_t initial) : current(initial), previous(0) {
|
||||
|
||||
}
|
||||
|
||||
bool operator==(const AnalysisState &other) const{
|
||||
AnalysisState(const AnalysisState &oldState) : current(oldState.current), previous(oldState.previous),
|
||||
memory(oldState.memory), pciSPICOFirmware(oldState.pciSPICOFirmware),
|
||||
pciSerDesFirmware(oldState.pciSerDesFirmware) {
|
||||
|
||||
}
|
||||
|
||||
bool operator==(const AnalysisState &other) const {
|
||||
return current == other.current && memory == other.memory;
|
||||
}
|
||||
|
||||
void setRegister(uint32_t addr, uint32_t value){
|
||||
void setRegister(uint32_t addr, uint32_t value) {
|
||||
memory[addr] = value;
|
||||
}
|
||||
|
||||
uint32_t getRegister(uint32_t addr) const{
|
||||
uint32_t getRegister(uint32_t addr) const {
|
||||
return memory.find(addr) == memory.end() ? 0 : memory.at(addr);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
bool Configuration::addEntry(const std::string &entry) {
|
||||
if(entry.empty() || entry[0] == '#'){
|
||||
if (entry.empty() || entry[0] == '#') {
|
||||
return false;
|
||||
}
|
||||
std::string fullKey;
|
||||
|
@ -40,36 +40,36 @@ bool Configuration::addEntry(const std::string &entry) {
|
|||
|
||||
uint32_t state = 0;
|
||||
|
||||
ConfigurationNode* currentNode = &mainNode;
|
||||
ConfigurationNode *currentNode = &mainNode;
|
||||
|
||||
for(size_t i = 0; i < entry.size(); ++i){
|
||||
for (size_t i = 0; i < entry.size(); ++i) {
|
||||
auto c = entry[i];
|
||||
if(state == 0){
|
||||
if((c == '.' || c == ' ' || c == '\t')){
|
||||
if(!currentKey.empty()){
|
||||
if (state == 0) {
|
||||
if ((c == '.' || c == ' ' || c == '\t')) {
|
||||
if (!currentKey.empty()) {
|
||||
currentNode = ¤tNode->getOrCreateSubNode(currentKey);
|
||||
|
||||
fullKey += currentKey;
|
||||
|
||||
currentKey.clear();
|
||||
|
||||
if(c == ' ' || c == '\t'){
|
||||
if (c == ' ' || c == '\t') {
|
||||
state = 1;
|
||||
}else{
|
||||
} else {
|
||||
fullKey += ".";
|
||||
}
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
currentKey += c;
|
||||
}
|
||||
} else if(state == 1){
|
||||
if((c == ' ' || c == '\t')){
|
||||
if(!currentKey.empty()){
|
||||
if(currentKey == "int"){
|
||||
} else if (state == 1) {
|
||||
if ((c == ' ' || c == '\t')) {
|
||||
if (!currentKey.empty()) {
|
||||
if (currentKey == "int") {
|
||||
currentNode->type = ConfigurationNode::Type::ValueInt;
|
||||
}else if(currentKey == "text"){
|
||||
} else if (currentKey == "text") {
|
||||
currentNode->type = ConfigurationNode::Type::ValueText;
|
||||
}else if(currentKey == "bool"){
|
||||
} else if (currentKey == "bool") {
|
||||
currentNode->type = ConfigurationNode::Type::ValueBool;
|
||||
}
|
||||
|
||||
|
@ -77,17 +77,17 @@ bool Configuration::addEntry(const std::string &entry) {
|
|||
|
||||
state = 2;
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
currentKey += c;
|
||||
}
|
||||
} else if(state == 2){
|
||||
if(i == (entry.size() - 1)){
|
||||
} else if (state == 2) {
|
||||
if (i == (entry.size() - 1)) {
|
||||
currentKey += c;
|
||||
currentNode->value = currentKey;
|
||||
if(std::find(orderedNodes.begin(), orderedNodes.end(), fullKey) == orderedNodes.end()){
|
||||
if (std::find(orderedNodes.begin(), orderedNodes.end(), fullKey) == orderedNodes.end()) {
|
||||
orderedNodes.emplace_back(fullKey);
|
||||
}
|
||||
}else if((c == ' ' || c == '\t') && currentKey.empty()){
|
||||
} else if ((c == ' ' || c == '\t') && currentKey.empty()) {
|
||||
|
||||
} else {
|
||||
currentKey += c;
|
||||
|
@ -99,37 +99,37 @@ bool Configuration::addEntry(const std::string &entry) {
|
|||
}
|
||||
|
||||
const Configuration::ConfigurationNode &Configuration::getEntry(const std::string &entry) const {
|
||||
if(entry.empty() || entry[0] == '#'){
|
||||
if (entry.empty() || entry[0] == '#') {
|
||||
return mainNode;
|
||||
}
|
||||
std::string currentKey;
|
||||
currentKey.reserve(16);
|
||||
|
||||
const ConfigurationNode* currentNode = &mainNode;
|
||||
const ConfigurationNode *currentNode = &mainNode;
|
||||
|
||||
for(char c : entry){
|
||||
if((c == '.' || c == ' ' || c == '\t')){
|
||||
if(!currentKey.empty()){
|
||||
for (char c : entry) {
|
||||
if ((c == '.' || c == ' ' || c == '\t')) {
|
||||
if (!currentKey.empty()) {
|
||||
currentNode = currentNode->getSubNode(currentKey);
|
||||
|
||||
if(currentNode == nullptr){
|
||||
if (currentNode == nullptr) {
|
||||
return mainNode;
|
||||
}
|
||||
|
||||
currentKey.clear();
|
||||
|
||||
if(c == ' ' || c == '\t'){
|
||||
if (c == ' ' || c == '\t') {
|
||||
return *currentNode;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
currentKey += c;
|
||||
}
|
||||
}
|
||||
|
||||
if(!currentKey.empty()) {
|
||||
if (!currentKey.empty()) {
|
||||
currentNode = currentNode->getSubNode(currentKey);
|
||||
if(currentNode != nullptr){
|
||||
if (currentNode != nullptr) {
|
||||
return *currentNode;
|
||||
}
|
||||
}
|
||||
|
@ -137,11 +137,13 @@ const Configuration::ConfigurationNode &Configuration::getEntry(const std::strin
|
|||
return mainNode;
|
||||
}
|
||||
|
||||
void Configuration::getAllEntriesForNode(std::vector<std::string> &entries, const Configuration::ConfigurationNode &node, const std::string &key) const {
|
||||
for(const auto& n : node.possibleNodes){
|
||||
if(n.type != ConfigurationNode::Type::Node){
|
||||
void
|
||||
Configuration::getAllEntriesForNode(std::vector<std::string> &entries, const Configuration::ConfigurationNode &node,
|
||||
const std::string &key) const {
|
||||
for (const auto &n : node.possibleNodes) {
|
||||
if (n.type != ConfigurationNode::Type::Node) {
|
||||
entries.push_back(key + n.name + " " + n.getTypeString() + " " + n.value);
|
||||
}else{
|
||||
} else {
|
||||
getAllEntriesForNode(entries, n, key + n.name + ".");
|
||||
}
|
||||
}
|
||||
|
@ -150,8 +152,8 @@ void Configuration::getAllEntriesForNode(std::vector<std::string> &entries, cons
|
|||
std::vector<std::string> Configuration::getAllEntries() const {
|
||||
std::vector<std::string> entries;
|
||||
|
||||
for(const auto& key : orderedNodes){
|
||||
auto& v = getEntry(key);
|
||||
for (const auto &key : orderedNodes) {
|
||||
auto &v = getEntry(key);
|
||||
entries.push_back(key + " " + v.getTypeString() + " " + v.value);
|
||||
}
|
||||
|
||||
|
@ -159,8 +161,8 @@ std::vector<std::string> Configuration::getAllEntries() const {
|
|||
}
|
||||
|
||||
Configuration::ConfigurationNode &Configuration::ConfigurationNode::getOrCreateSubNode(const std::string &k) {
|
||||
for (auto& node : possibleNodes){
|
||||
if(node.name == k){
|
||||
for (auto &node : possibleNodes) {
|
||||
if (node.name == k) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
@ -170,8 +172,8 @@ Configuration::ConfigurationNode &Configuration::ConfigurationNode::getOrCreateS
|
|||
}
|
||||
|
||||
const Configuration::ConfigurationNode *Configuration::ConfigurationNode::getSubNode(const std::string &k) const {
|
||||
for (auto& node : possibleNodes){
|
||||
if(node.name == k){
|
||||
for (auto &node : possibleNodes) {
|
||||
if (node.name == k) {
|
||||
return &node;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
class Configuration {
|
||||
public:
|
||||
|
||||
Configuration(){
|
||||
Configuration() {
|
||||
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,8 @@ public:
|
|||
ValueBool,
|
||||
} type;
|
||||
|
||||
ConfigurationNode(std::string name, ConfigurationNode::Type type = ConfigurationNode::Type::Node) : name(std::move(name)), type(type){
|
||||
ConfigurationNode(std::string name, ConfigurationNode::Type type = ConfigurationNode::Type::Node) : name(
|
||||
std::move(name)), type(type) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -55,7 +56,7 @@ public:
|
|||
std::vector<ConfigurationNode> possibleNodes;
|
||||
std::string value;
|
||||
|
||||
std::string getTypeString() const{
|
||||
std::string getTypeString() const {
|
||||
switch (type) {
|
||||
case Type::Node:
|
||||
return "node";
|
||||
|
@ -70,19 +71,19 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
const ConfigurationNode* getSubNode(const std::string& k) const;
|
||||
const ConfigurationNode *getSubNode(const std::string &k) const;
|
||||
|
||||
ConfigurationNode& getOrCreateSubNode(const std::string& k);
|
||||
ConfigurationNode &getOrCreateSubNode(const std::string &k);
|
||||
|
||||
bool getBool() const{
|
||||
bool getBool() const {
|
||||
return value == "true" || value == "1";
|
||||
}
|
||||
|
||||
int getInteger() const{
|
||||
int getInteger() const {
|
||||
return std::stoi(value, nullptr, 0);
|
||||
}
|
||||
|
||||
const std::string& getText() const{
|
||||
const std::string &getText() const {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
@ -92,10 +93,11 @@ public:
|
|||
|
||||
std::vector<std::string> getAllEntries() const;
|
||||
|
||||
void getAllEntriesForNode(std::vector<std::string>& entries, const ConfigurationNode& node, const std::string& key) const;
|
||||
void getAllEntriesForNode(std::vector<std::string> &entries, const ConfigurationNode &node,
|
||||
const std::string &key) const;
|
||||
|
||||
const ConfigurationNode& getEntry(const std::string& entry) const;
|
||||
const ConfigurationNode &getEntry(const std::string &entry) const;
|
||||
|
||||
bool addEntry(const std::string& entry);
|
||||
bool addEntry(const std::string &entry);
|
||||
|
||||
};
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
std::unique_ptr<Instruction::Instruction> ImageFormat::NULL_INSTRUCTION(nullptr);
|
||||
|
||||
ImageFormat ImageFormat::fromBytes(const std::vector<uint8_t>& imageBytes) {
|
||||
ImageFormat ImageFormat::fromBytes(const std::vector<uint8_t> &imageBytes) {
|
||||
ImageFormat image;
|
||||
|
||||
image.baseImage = imageBytes;
|
||||
|
@ -53,11 +53,12 @@ ImageFormat ImageFormat::fromBytes(const std::vector<uint8_t>& imageBytes) {
|
|||
image.header.baseAddress |= imageBytes[offset++] << 8;
|
||||
image.header.baseAddress |= imageBytes[offset++];
|
||||
|
||||
printf("SPEED: 0x%02x MODE: 0x%02x BOOT: 0x%08x\n", image.header.speed, image.header.mode, image.header.baseAddress);
|
||||
printf("SPEED: 0x%02x MODE: 0x%02x BOOT: 0x%08x\n", image.header.speed, image.header.mode,
|
||||
image.header.baseAddress);
|
||||
|
||||
offset = CFG_SIGNATURE;
|
||||
uint8_t currentCharacter;
|
||||
while ((currentCharacter = imageBytes[offset++]) != 0xFF){
|
||||
while ((currentCharacter = imageBytes[offset++]) != 0xFF) {
|
||||
image.imageSignature += currentCharacter;
|
||||
}
|
||||
|
||||
|
@ -80,21 +81,21 @@ ImageFormat ImageFormat::fromBytes(const std::vector<uint8_t>& imageBytes) {
|
|||
image.cfg.length <<= 4;
|
||||
|
||||
|
||||
if(image.cfg.version == 0){
|
||||
if(image.cfg.fileFormat == 1){
|
||||
if (image.cfg.version == 0) {
|
||||
if (image.cfg.fileFormat == 1) {
|
||||
offset = image.cfgHeader.base + CFG_LENGTH;
|
||||
uint32_t imageSize = image.cfg.length;
|
||||
uint32_t bytesCnt = 0;
|
||||
|
||||
while (bytesCnt < imageSize){
|
||||
while (bytesCnt < imageSize) {
|
||||
std::string currentEntry;
|
||||
uint8_t character;
|
||||
do{
|
||||
do {
|
||||
character = imageBytes[offset++];
|
||||
++bytesCnt;
|
||||
if(character != 0xFF){
|
||||
if (character != 0xFF) {
|
||||
currentEntry += character;
|
||||
if(character == '\n'){
|
||||
if (character == '\n') {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -102,8 +103,8 @@ ImageFormat ImageFormat::fromBytes(const std::vector<uint8_t>& imageBytes) {
|
|||
}
|
||||
} while (true);
|
||||
|
||||
if(!currentEntry.empty()){
|
||||
if(currentEntry[currentEntry.size() - 1] == '\n'){
|
||||
if (!currentEntry.empty()) {
|
||||
if (currentEntry[currentEntry.size() - 1] == '\n') {
|
||||
currentEntry.resize(currentEntry.size() - 1);
|
||||
}
|
||||
image.bootConfig.addEntry(currentEntry);
|
||||
|
@ -124,13 +125,12 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
|
|||
uint32_t offset = 0;
|
||||
|
||||
|
||||
|
||||
bytes[offset++] = (header.reserved) | ((uint8_t) header.speed << 3) | ((uint8_t) header.mode << 6);
|
||||
bytes[offset++] = (header.baseAddress >> 16) & 0xFF;
|
||||
bytes[offset++] = (header.baseAddress >> 8) & 0xFF;
|
||||
bytes[offset++] = header.baseAddress & 0xFF;
|
||||
|
||||
for(; offset < CFG_HEADER; ++offset){
|
||||
for (; offset < CFG_HEADER; ++offset) {
|
||||
bytes[offset] = baseImage[offset];
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
|
|||
bytes[offset++] = (cfgHeader.base >> 8) & 0xFF;
|
||||
bytes[offset++] = cfgHeader.base & 0xFF;
|
||||
|
||||
for(; offset < CFG_SIGNATURE; ++offset){
|
||||
for (; offset < CFG_SIGNATURE; ++offset) {
|
||||
bytes[offset] = baseImage[offset];
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
|
|||
|
||||
offset += imageSignature.length();
|
||||
|
||||
for(; offset < cfgHeader.base; ++offset){
|
||||
for (; offset < cfgHeader.base; ++offset) {
|
||||
bytes[offset] = baseImage[offset];
|
||||
}
|
||||
|
||||
|
@ -157,13 +157,13 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
|
|||
bytes[offset++] = ((cfg.length >> 4) >> 8) & 0xFF;
|
||||
bytes[offset++] = (cfg.length >> 4) & 0xFF;
|
||||
|
||||
for(; offset < cfgHeader.base + CFG_LENGTH; ++offset){
|
||||
for (; offset < cfgHeader.base + CFG_LENGTH; ++offset) {
|
||||
bytes[offset] = baseImage[offset];
|
||||
}
|
||||
|
||||
if(cfg.version == 0){
|
||||
if(cfg.fileFormat == 1){
|
||||
for (const auto& entry : bootConfig.getAllEntries()) {
|
||||
if (cfg.version == 0) {
|
||||
if (cfg.fileFormat == 1) {
|
||||
for (const auto &entry : bootConfig.getAllEntries()) {
|
||||
std::copy(entry.begin(), entry.end(), bytes.begin() + offset);
|
||||
offset += entry.length();
|
||||
bytes[offset++] = '\n';
|
||||
|
@ -174,7 +174,7 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
|
|||
|
||||
std::copy(baseImage.begin() + offset, baseImage.end(), bytes.begin() + offset);
|
||||
|
||||
for (const auto& entry : instructions){
|
||||
for (const auto &entry : instructions) {
|
||||
auto data = entry.second->toBytes();
|
||||
std::copy(data.begin(), data.end(), bytes.begin() + entry.second->getAddress());
|
||||
}
|
||||
|
@ -183,7 +183,6 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
|
|||
}
|
||||
|
||||
|
||||
|
||||
void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
|
||||
std::queue<AnalysisState> savedStates;
|
||||
std::vector<AnalysisState> branchingStates;
|
||||
|
@ -197,63 +196,70 @@ void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
|
|||
uint32_t maxUnchangedExecutions = 1000;
|
||||
uint32_t maxTotalExecutions = 20000;
|
||||
|
||||
while(!savedStates.empty()){
|
||||
while (!savedStates.empty()) {
|
||||
AnalysisState state = savedStates.front();
|
||||
savedStates.pop();
|
||||
|
||||
uint32_t loopsSinceLastModification = 0;
|
||||
uint32_t absoluteLoops = 0;
|
||||
|
||||
do{
|
||||
do {
|
||||
|
||||
jumpsUsed[state.current] = true;
|
||||
|
||||
if(state.current >= 0x100000 || (findInstructionByAddress(state.current) == nullptr && findInstructionByAddress(state.current, true) != nullptr)){ //Prevent arbitrary decoding in between decoded instructions
|
||||
if (state.current >= 0x100000 || (findInstructionByAddress(state.current) == nullptr &&
|
||||
findInstructionByAddress(state.current, true) !=
|
||||
nullptr)) { //Prevent arbitrary decoding in between decoded instructions
|
||||
break;
|
||||
}else if(findInstructionByAddress(state.current) == nullptr){
|
||||
auto decodedInstruction = Instruction::Instruction::decodeInstructionFromBytes(state.current, baseImage);
|
||||
} else if (findInstructionByAddress(state.current) == nullptr) {
|
||||
auto decodedInstruction = Instruction::Instruction::decodeInstructionFromBytes(state.current,
|
||||
baseImage);
|
||||
instructions[decodedInstruction->getAddress()] = std::move(decodedInstruction);
|
||||
}
|
||||
|
||||
if(loopsSinceLastModification > 800){
|
||||
if (loopsSinceLastModification > 800) {
|
||||
//std::cout << "TOO UNCHANGED " << std::hex << state.previous << " -> " << std::hex << state.current << "\n";
|
||||
|
||||
}
|
||||
|
||||
state.previous = state.current;
|
||||
auto& instruction = findInstructionByAddress(state.current);
|
||||
auto &instruction = findInstructionByAddress(state.current);
|
||||
|
||||
state.current &= 0xfffffffc;
|
||||
|
||||
if(instruction == nullptr){
|
||||
if (instruction == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto possibleBranches = instruction->execute(state);
|
||||
|
||||
if((instruction->getCommand() == Instruction::Instruction::CommandOp::JUMP || instruction->getCommand() == Instruction::Instruction::CommandOp::RETURN) && jumpsUsed.find(instruction->getEndAddress()) == jumpsUsed.end()){
|
||||
if ((instruction->getCommand() == Instruction::Instruction::CommandOp::JUMP ||
|
||||
instruction->getCommand() == Instruction::Instruction::CommandOp::RETURN) &&
|
||||
jumpsUsed.find(instruction->getEndAddress()) == jumpsUsed.end()) {
|
||||
jumpsUsed[instruction->getEndAddress()] = false;
|
||||
}
|
||||
|
||||
if(state.current == 0){
|
||||
if (state.current == 0) {
|
||||
//std::cout << "EXIT DUE TO END " << std::hex << state.previous << " -> " << std::hex << state.current << "\n";
|
||||
break;
|
||||
}
|
||||
|
||||
if(instruction->getCommand() == Instruction::Instruction::CommandOp::JUMP){
|
||||
if (instruction->getCommand() == Instruction::Instruction::CommandOp::JUMP) {
|
||||
uint32_t nextAddress = instruction->getAddress() - 1;
|
||||
while (true){
|
||||
const auto& previousInstruction = findInstructionByAddress(nextAddress, true);
|
||||
if(previousInstruction != nullptr && previousInstruction->getCommand() == Instruction::Instruction::CommandOp::WRITE){
|
||||
const auto& writeInstruction = reinterpret_cast<const std::unique_ptr<Instruction::Write>&>(previousInstruction);
|
||||
if(
|
||||
while (true) {
|
||||
const auto &previousInstruction = findInstructionByAddress(nextAddress, true);
|
||||
if (previousInstruction != nullptr &&
|
||||
previousInstruction->getCommand() == Instruction::Instruction::CommandOp::WRITE) {
|
||||
const auto &writeInstruction = reinterpret_cast<const std::unique_ptr<Instruction::Write> &>(previousInstruction);
|
||||
if (
|
||||
(
|
||||
writeInstruction->address == (uint32_t)KnownRegisters::MGMT_SCRATCH_1
|
||||
|| (writeInstruction->address >= (uint32_t)KnownRegisters::BSM_SCRATCH_START && writeInstruction->address < (uint32_t)KnownRegisters::BSM_SCRATCH_END)
|
||||
writeInstruction->address == (uint32_t) KnownRegisters::MGMT_SCRATCH_1
|
||||
|| (writeInstruction->address >= (uint32_t) KnownRegisters::BSM_SCRATCH_START &&
|
||||
writeInstruction->address < (uint32_t) KnownRegisters::BSM_SCRATCH_END)
|
||||
)
|
||||
&& writeInstruction->data.size() == 1
|
||||
){ //This is commonly used before jumps to mark return values or switch statements
|
||||
if(jumpsUsed.find(writeInstruction->data[0]) == jumpsUsed.end()){
|
||||
) { //This is commonly used before jumps to mark return values or switch statements
|
||||
if (jumpsUsed.find(writeInstruction->data[0]) == jumpsUsed.end()) {
|
||||
jumpsUsed[writeInstruction->data[0]] = false;
|
||||
}
|
||||
}
|
||||
|
@ -266,22 +272,22 @@ void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
|
|||
}
|
||||
|
||||
|
||||
for(const auto& branch : possibleBranches){
|
||||
for (const auto &branch : possibleBranches) {
|
||||
AnalysisState newState(state);
|
||||
newState.current = branch.first & 0xfffffffc;
|
||||
for(const auto& entry : branch.second){
|
||||
for (const auto &entry : branch.second) {
|
||||
newState.setRegister(entry.first, entry.second);
|
||||
}
|
||||
|
||||
bool stateExists = false;
|
||||
for(const auto& previousState : branchingStates){
|
||||
if(newState.previous == previousState.previous && newState.current == previousState.current){
|
||||
for (const auto &previousState : branchingStates) {
|
||||
if (newState.previous == previousState.previous && newState.current == previousState.current) {
|
||||
stateExists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!stateExists){
|
||||
if (!stateExists) {
|
||||
loopsSinceLastModification = 0;
|
||||
savedStates.push(newState);
|
||||
branchingStates.push_back(std::move(newState));
|
||||
|
@ -289,9 +295,9 @@ void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
|
|||
}
|
||||
} while (loopsSinceLastModification++ < maxUnchangedExecutions && absoluteLoops++ < maxTotalExecutions);
|
||||
|
||||
if(savedStates.empty()){
|
||||
for(auto& visited : jumpsUsed){
|
||||
if(!visited.second && visited.first >= offset && visited.first <= 0x100000){
|
||||
if (savedStates.empty()) {
|
||||
for (auto &visited : jumpsUsed) {
|
||||
if (!visited.second && visited.first >= offset && visited.first <= 0x100000) {
|
||||
baseState.current = visited.first;
|
||||
savedStates.push(baseState);
|
||||
break;
|
||||
|
@ -299,6 +305,8 @@ void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
|
|||
}
|
||||
}
|
||||
|
||||
std::cerr << "Next state, branched states left: " << std::dec << savedStates.size() << /*", executed states: " << std::dec << createdStates.size() <<*/ ", total instructions decoded: " << std::dec << instructions.size() << "\n";
|
||||
std::cerr << "Next state, branched states left: " << std::dec << savedStates.size()
|
||||
<< /*", executed states: " << std::dec << createdStates.size() <<*/ ", total instructions decoded: "
|
||||
<< std::dec << instructions.size() << "\n";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include "Configuration.h"
|
||||
#include "instructions/Instruction.h"
|
||||
|
||||
class ImageFormat{
|
||||
class ImageFormat {
|
||||
|
||||
public:
|
||||
|
||||
|
@ -59,25 +59,25 @@ public:
|
|||
};
|
||||
|
||||
|
||||
static ImageFormat fromBytes(const std::vector<uint8_t>& image);
|
||||
static ImageFormat fromBytes(const std::vector<uint8_t> &image);
|
||||
|
||||
void decodeAnalyzeInstructionsAt(uint32_t offset);
|
||||
|
||||
std::unique_ptr<Instruction::Instruction>& findInstructionByAddress(uint32_t addr, bool indirect = false){
|
||||
if(instructions.find(addr) != instructions.end()){
|
||||
std::unique_ptr<Instruction::Instruction> &findInstructionByAddress(uint32_t addr, bool indirect = false) {
|
||||
if (instructions.find(addr) != instructions.end()) {
|
||||
return instructions.find(addr)->second;
|
||||
}
|
||||
|
||||
if(indirect){
|
||||
for(auto& instruction : instructions){
|
||||
if(
|
||||
if (indirect) {
|
||||
for (auto &instruction : instructions) {
|
||||
if (
|
||||
(instruction.second->getEndAddress() == 0 && addr == instruction.second->getAddress())
|
||||
|| (
|
||||
instruction.second->getEndAddress() != 0
|
||||
&& addr >= instruction.second->getAddress()
|
||||
&& addr < instruction.second->getEndAddress()
|
||||
)
|
||||
){
|
||||
)
|
||||
) {
|
||||
return instruction.second;
|
||||
}
|
||||
}
|
||||
|
@ -86,27 +86,27 @@ public:
|
|||
return NULL_INSTRUCTION;
|
||||
}
|
||||
|
||||
ImageFormat(){
|
||||
ImageFormat() {
|
||||
|
||||
}
|
||||
|
||||
const auto& getHeader() const{
|
||||
const auto &getHeader() const {
|
||||
return header;
|
||||
}
|
||||
|
||||
const auto& getInstructions() const{
|
||||
const auto &getInstructions() const {
|
||||
return instructions;
|
||||
}
|
||||
|
||||
const auto& getBaseImage() const{
|
||||
const auto &getBaseImage() const {
|
||||
return baseImage;
|
||||
}
|
||||
|
||||
const auto& getBootConfig() const{
|
||||
const auto &getBootConfig() const {
|
||||
return bootConfig;
|
||||
}
|
||||
|
||||
auto& getModifiableBootConfig(){
|
||||
auto &getModifiableBootConfig() {
|
||||
return bootConfig;
|
||||
}
|
||||
|
||||
|
@ -117,10 +117,10 @@ public:
|
|||
private:
|
||||
|
||||
struct {
|
||||
uint8_t reserved : 3;
|
||||
ImageFormat::HeaderSpeed speed : 3;
|
||||
ImageFormat::HeaderMode mode : 2;
|
||||
uint32_t baseAddress : 24;
|
||||
uint8_t reserved: 3;
|
||||
ImageFormat::HeaderSpeed speed: 3;
|
||||
ImageFormat::HeaderMode mode: 2;
|
||||
uint32_t baseAddress: 24;
|
||||
} header;
|
||||
|
||||
static const int CFG_SIGNATURE = 0x100;
|
||||
|
@ -130,14 +130,14 @@ private:
|
|||
static std::unique_ptr<Instruction::Instruction> NULL_INSTRUCTION;
|
||||
|
||||
struct {
|
||||
uint8_t length : 8;
|
||||
uint32_t base : 24;
|
||||
uint8_t length: 8;
|
||||
uint32_t base: 24;
|
||||
} cfgHeader;
|
||||
|
||||
struct {
|
||||
uint8_t fileFormat : 8;
|
||||
uint8_t version : 8;
|
||||
uint16_t length : 16;
|
||||
uint8_t fileFormat: 8;
|
||||
uint8_t version: 8;
|
||||
uint16_t length: 16;
|
||||
} cfg;
|
||||
|
||||
Configuration bootConfig;
|
||||
|
|
|
@ -31,11 +31,12 @@
|
|||
#include "Registers.h"
|
||||
|
||||
|
||||
|
||||
std::string getRegisterName(KnownRegisters addr) {
|
||||
if((uint32_t)addr >= (uint32_t)KnownRegisters::BSM_SCRATCH_START && (uint32_t)addr <= (uint32_t)KnownRegisters::BSM_SCRATCH_END){
|
||||
if ((uint32_t) addr >= (uint32_t) KnownRegisters::BSM_SCRATCH_START &&
|
||||
(uint32_t) addr <= (uint32_t) KnownRegisters::BSM_SCRATCH_END) {
|
||||
std::stringstream s;
|
||||
s << "BSM_SCRATCH[0x" << std::hex << std::setw(3) << std::setfill('0') << (((uint32_t)addr) - (uint32_t)KnownRegisters::BSM_SCRATCH_START) << "]";
|
||||
s << "BSM_SCRATCH[0x" << std::hex << std::setw(3) << std::setfill('0')
|
||||
<< (((uint32_t) addr) - (uint32_t) KnownRegisters::BSM_SCRATCH_START) << "]";
|
||||
return s.str();
|
||||
}
|
||||
switch (addr) {
|
||||
|
@ -164,20 +165,21 @@ std::string getRegisterName(KnownRegisters addr) {
|
|||
|
||||
}
|
||||
std::stringstream s;
|
||||
s << "register[0x" << std::hex << std::setw(6) << std::setfill('0') << (uint32_t)addr << "]";
|
||||
s << "register[0x" << std::hex << std::setw(6) << std::setfill('0') << (uint32_t) addr << "]";
|
||||
return s.str();
|
||||
}
|
||||
|
||||
std::string getAddressRegisterName(uint32_t addr, uint8_t offset){
|
||||
std::string getAddressRegisterName(uint32_t addr, uint8_t offset) {
|
||||
std::stringstream s;
|
||||
if(offset){
|
||||
s << getRegisterName(static_cast<KnownRegisters>((uint32_t)KnownRegisters::BSM_ADDR_OFFSET_0 + offset)) << " + " << "0x" << std::hex << std::setw(6) << std::setfill('0') << addr;
|
||||
if (offset) {
|
||||
s << getRegisterName(static_cast<KnownRegisters>((uint32_t) KnownRegisters::BSM_ADDR_OFFSET_0 + offset))
|
||||
<< " + " << "0x" << std::hex << std::setw(6) << std::setfill('0') << addr;
|
||||
} else {
|
||||
s << getRegisterName(static_cast<KnownRegisters>(addr));
|
||||
}
|
||||
return s.str();
|
||||
}
|
||||
|
||||
KnownRegisters getScratchRegister(uint32_t offset){
|
||||
return static_cast<KnownRegisters>((uint32_t)KnownRegisters::BSM_SCRATCH_START + offset);
|
||||
KnownRegisters getScratchRegister(uint32_t offset) {
|
||||
return static_cast<KnownRegisters>((uint32_t) KnownRegisters::BSM_SCRATCH_START + offset);
|
||||
}
|
|
@ -27,7 +27,8 @@
|
|||
|
||||
#include "SmallFirmwareFormat.h"
|
||||
|
||||
SmallFirmwareFormat SmallFirmwareFormat::fromBSMLoad(const std::vector<uint32_t>& parameters, uint32_t parameterOffset) {
|
||||
SmallFirmwareFormat
|
||||
SmallFirmwareFormat::fromBSMLoad(const std::vector<uint32_t> ¶meters, uint32_t parameterOffset) {
|
||||
SmallFirmwareFormat fw;
|
||||
|
||||
for (auto it = parameters.begin() + parameterOffset; it != parameters.end(); ++it) {
|
||||
|
|
|
@ -34,12 +34,13 @@
|
|||
class SmallFirmwareFormat {
|
||||
public:
|
||||
|
||||
static SmallFirmwareFormat fromBSMLoad(const std::vector<uint32_t>& parameters, uint32_t parameterOffset);
|
||||
static SmallFirmwareFormat fromBSMLoad(const std::vector<uint32_t> ¶meters, uint32_t parameterOffset);
|
||||
|
||||
SmallFirmwareFormat(){
|
||||
SmallFirmwareFormat() {
|
||||
|
||||
}
|
||||
SmallFirmwareFormat(const SmallFirmwareFormat& other) : firmware(other.firmware){
|
||||
|
||||
SmallFirmwareFormat(const SmallFirmwareFormat &other) : firmware(other.firmware) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -59,19 +59,20 @@ void Instruction::Branch::fromBytes(uint32_t offset, const std::vector<uint8_t>
|
|||
jumpAddress |= bytes[offset++];
|
||||
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
||||
std::string Instruction::Branch::toString() const {
|
||||
std::stringstream op;
|
||||
op << "BRANCH IF (" << getAddressRegisterName(address, addressOffset) << " & 0x" << std::hex << std::setw(8) << std::setfill('0') << mask << ")";
|
||||
if(equality){
|
||||
op << "BRANCH IF (" << getAddressRegisterName(address, addressOffset) << " & 0x" << std::hex << std::setw(8)
|
||||
<< std::setfill('0') << mask << ")";
|
||||
if (equality) {
|
||||
op << " == ";
|
||||
}else{
|
||||
} else {
|
||||
op << " != ";
|
||||
}
|
||||
op << "0x" << std::hex << std::setw(8) << std::setfill('0') << value << " JUMP 0x" << std::hex << std::setw(6) << std::setfill('0') << jumpAddress;
|
||||
op << "0x" << std::hex << std::setw(8) << std::setfill('0') << value << " JUMP 0x" << std::hex << std::setw(6)
|
||||
<< std::setfill('0') << jumpAddress;
|
||||
|
||||
return op.str();
|
||||
}
|
||||
|
@ -80,22 +81,25 @@ std::vector<uint32_t> Instruction::Branch::getPossibleBranches() const {
|
|||
return std::vector<uint32_t>{_endAddress, jumpAddress};
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruction::Branch::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::Branch::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> branches;
|
||||
|
||||
uint32_t memoryOffset = state.getAddressOffset(addressOffset);
|
||||
|
||||
if((state.getRegister(memoryOffset + address) & mask) == value){
|
||||
if ((state.getRegister(memoryOffset + address) & mask) == value) {
|
||||
state.current = equality ? jumpAddress : _endAddress;
|
||||
|
||||
std::unordered_map<uint32_t, uint32_t> branchedState;
|
||||
branchedState[memoryOffset + address] = state.getRegister(memoryOffset + address) | (equality ? ~value & mask : value);
|
||||
branchedState[memoryOffset + address] =
|
||||
state.getRegister(memoryOffset + address) | (equality ? ~value & mask : value);
|
||||
branches.emplace_back(equality ? _endAddress : jumpAddress, std::move(branchedState));
|
||||
}else{
|
||||
} else {
|
||||
state.current = equality ? _endAddress : jumpAddress;
|
||||
|
||||
std::unordered_map<uint32_t, uint32_t> branchedState;
|
||||
branchedState[memoryOffset + address] = state.getRegister(memoryOffset + address) | (equality ? value : ~value & mask);
|
||||
branchedState[memoryOffset + address] =
|
||||
state.getRegister(memoryOffset + address) | (equality ? value : ~value & mask);
|
||||
branches.emplace_back(equality ? jumpAddress : _endAddress, std::move(branchedState));
|
||||
}
|
||||
|
||||
|
@ -105,7 +109,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
std::vector<uint8_t> Instruction::Branch::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand() | (equality << 2) | addressOffset);
|
||||
bytes.emplace_back((uint8_t) getCommand() | (equality << 2) | addressOffset);
|
||||
|
||||
bytes.emplace_back((address >> 16) & 0xFF);
|
||||
bytes.emplace_back((address >> 8) & 0xFF);
|
||||
|
|
|
@ -29,18 +29,18 @@
|
|||
|
||||
#include "Instruction.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
class Branch : public Instruction {
|
||||
public:
|
||||
Branch(){
|
||||
Branch() {
|
||||
|
||||
}
|
||||
|
||||
CommandOp getCommand() const override{
|
||||
CommandOp getCommand() const override {
|
||||
return CommandOp::BRANCH;
|
||||
};
|
||||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
|
@ -48,7 +48,8 @@ namespace Instruction{
|
|||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> execute(AnalysisState& state) const override;
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
execute(AnalysisState &state) const override;
|
||||
|
||||
|
||||
uint8_t addressOffset;
|
||||
|
|
|
@ -55,13 +55,13 @@ void Instruction::Calc::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
addressTarget |= bytes[offset++];
|
||||
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
||||
std::string Instruction::Calc::toString() const {
|
||||
std::stringstream op;
|
||||
op << "CALC " << getAddressRegisterName(addressDestination, addressOffset) << " = " << getAddressRegisterName(addressSource, addressOffset);
|
||||
op << "CALC " << getAddressRegisterName(addressDestination, addressOffset) << " = "
|
||||
<< getAddressRegisterName(addressSource, addressOffset);
|
||||
switch (operation) {
|
||||
case Operation::AND:
|
||||
op << " & ";
|
||||
|
@ -96,7 +96,8 @@ std::vector<uint32_t> Instruction::Calc::getPossibleBranches() const {
|
|||
return std::vector<uint32_t>{_endAddress};
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruction::Calc::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::Calc::execute(AnalysisState &state) const {
|
||||
|
||||
uint32_t memoryOffset = state.getAddressOffset(addressOffset);
|
||||
|
||||
|
@ -123,7 +124,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
state.setRegister(addressDestination, v_a >> v_b);
|
||||
break;
|
||||
case Operation::ARSHIFT:
|
||||
state.setRegister(addressDestination, (uint32_t)((int32_t)v_a >> v_b));
|
||||
state.setRegister(addressDestination, (uint32_t) ((int32_t) v_a >> v_b));
|
||||
break;
|
||||
case Operation::UNDEFINED:
|
||||
break;
|
||||
|
@ -137,7 +138,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
std::vector<uint8_t> Instruction::Calc::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand() | ((uint8_t)operation << 2) | addressOffset);
|
||||
bytes.emplace_back((uint8_t) getCommand() | ((uint8_t) operation << 2) | addressOffset);
|
||||
|
||||
bytes.emplace_back((addressDestination >> 16) & 0xFF);
|
||||
bytes.emplace_back((addressDestination >> 8) & 0xFF);
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
#include "Instruction.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
class Calc : public Instruction {
|
||||
public:
|
||||
|
||||
|
@ -44,15 +44,15 @@ namespace Instruction{
|
|||
UNDEFINED = 7
|
||||
};
|
||||
|
||||
Calc(){
|
||||
Calc() {
|
||||
|
||||
}
|
||||
|
||||
CommandOp getCommand() const override{
|
||||
CommandOp getCommand() const override {
|
||||
return CommandOp::CALC;
|
||||
};
|
||||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
|
@ -60,7 +60,8 @@ namespace Instruction{
|
|||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> execute(AnalysisState& state) const override;
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
execute(AnalysisState &state) const override;
|
||||
|
||||
|
||||
Operation operation;
|
||||
|
|
|
@ -55,13 +55,13 @@ void Instruction::CalcImm::fromBytes(uint32_t offset, const std::vector<uint8_t>
|
|||
value |= bytes[offset++];
|
||||
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
||||
std::string Instruction::CalcImm::toString() const {
|
||||
std::stringstream op;
|
||||
op << "CALC_IMM " << getAddressRegisterName(addressDestination, addressOffset) << " = " << getAddressRegisterName(addressSource, addressOffset);
|
||||
op << "CALC_IMM " << getAddressRegisterName(addressDestination, addressOffset) << " = "
|
||||
<< getAddressRegisterName(addressSource, addressOffset);
|
||||
switch (operation) {
|
||||
case Calc::Operation::AND:
|
||||
op << " & ";
|
||||
|
@ -96,7 +96,8 @@ std::vector<uint32_t> Instruction::CalcImm::getPossibleBranches() const {
|
|||
return std::vector<uint32_t>{_endAddress};
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruction::CalcImm::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::CalcImm::execute(AnalysisState &state) const {
|
||||
|
||||
uint32_t memoryOffset = state.getAddressOffset(addressOffset);
|
||||
|
||||
|
@ -122,7 +123,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
state.setRegister(addressDestination, v_a >> value);
|
||||
break;
|
||||
case Calc::Operation::ARSHIFT:
|
||||
state.setRegister(addressDestination, (uint32_t)((int32_t)v_a >> value));
|
||||
state.setRegister(addressDestination, (uint32_t) ((int32_t) v_a >> value));
|
||||
break;
|
||||
case Calc::Operation::UNDEFINED:
|
||||
break;
|
||||
|
@ -136,7 +137,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
std::vector<uint8_t> Instruction::CalcImm::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand() | ((uint8_t)operation << 2) | addressOffset);
|
||||
bytes.emplace_back((uint8_t) getCommand() | ((uint8_t) operation << 2) | addressOffset);
|
||||
|
||||
bytes.emplace_back((addressDestination >> 16) & 0xFF);
|
||||
bytes.emplace_back((addressDestination >> 8) & 0xFF);
|
||||
|
|
|
@ -30,19 +30,19 @@
|
|||
#include "Instruction.h"
|
||||
#include "Calc.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
class CalcImm : public Instruction {
|
||||
public:
|
||||
|
||||
CalcImm(){
|
||||
CalcImm() {
|
||||
|
||||
}
|
||||
|
||||
CommandOp getCommand() const override{
|
||||
CommandOp getCommand() const override {
|
||||
return CommandOp::CALC_IMM;
|
||||
};
|
||||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
|
@ -50,7 +50,8 @@ namespace Instruction{
|
|||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> execute(AnalysisState& state) const override;
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
execute(AnalysisState &state) const override;
|
||||
|
||||
|
||||
Calc::Operation operation;
|
||||
|
|
|
@ -50,13 +50,14 @@ void Instruction::Copy::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
addressBB |= bytes[offset++];
|
||||
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
||||
std::string Instruction::Copy::toString() const {
|
||||
std::stringstream op;
|
||||
op << "COPY " << std::dec << (uint32_t) count << " WORDS FROM " << getAddressRegisterName(addressAA, addressOffsetAA) << " TO " << getAddressRegisterName(addressBB, addressOffsetBB);
|
||||
op << "COPY " << std::dec << (uint32_t) count << " WORDS FROM "
|
||||
<< getAddressRegisterName(addressAA, addressOffsetAA) << " TO "
|
||||
<< getAddressRegisterName(addressBB, addressOffsetBB);
|
||||
return op.str();
|
||||
}
|
||||
|
||||
|
@ -64,12 +65,13 @@ std::vector<uint32_t> Instruction::Copy::getPossibleBranches() const {
|
|||
return std::vector<uint32_t>{_endAddress};
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruction::Copy::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::Copy::execute(AnalysisState &state) const {
|
||||
|
||||
uint32_t memoryOffsetAA = state.getAddressOffset(addressOffsetAA);
|
||||
uint32_t memoryOffsetBB = state.getAddressOffset(addressOffsetBB);
|
||||
|
||||
for(uint32_t i = 0; i < count; ++i){
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
state.setRegister(memoryOffsetAA + addressOffsetAA + i, state.getRegister(memoryOffsetBB + addressBB));
|
||||
}
|
||||
|
||||
|
@ -82,7 +84,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
std::vector<uint8_t> Instruction::Copy::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand() | ((count - 1) << 4) | (addressOffsetBB << 2) | addressOffsetAA);
|
||||
bytes.emplace_back((uint8_t) getCommand() | ((count - 1) << 4) | (addressOffsetBB << 2) | addressOffsetAA);
|
||||
|
||||
bytes.emplace_back((addressAA >> 16) & 0xFF);
|
||||
bytes.emplace_back((addressAA >> 8) & 0xFF);
|
||||
|
|
|
@ -29,18 +29,18 @@
|
|||
|
||||
#include "Instruction.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
class Copy : public Instruction {
|
||||
public:
|
||||
Copy(){
|
||||
Copy() {
|
||||
|
||||
}
|
||||
|
||||
CommandOp getCommand() const override{
|
||||
CommandOp getCommand() const override {
|
||||
return CommandOp::COPY;
|
||||
};
|
||||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
|
@ -48,7 +48,8 @@ namespace Instruction{
|
|||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> execute(AnalysisState& state) const override;
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
execute(AnalysisState &state) const override;
|
||||
|
||||
|
||||
uint8_t count;
|
||||
|
|
|
@ -47,7 +47,8 @@ std::vector<uint32_t> Instruction::End::getPossibleBranches() const {
|
|||
return std::vector<uint32_t>();
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruction::End::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::End::execute(AnalysisState &state) const {
|
||||
state.current = 0;
|
||||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
|
@ -56,7 +57,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
std::vector<uint8_t> Instruction::End::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand());
|
||||
bytes.emplace_back((uint8_t) getCommand());
|
||||
|
||||
bytes.emplace_back((reserved >> 16) & 0xFF);
|
||||
bytes.emplace_back((reserved >> 8) & 0xFF);
|
||||
|
|
|
@ -29,18 +29,18 @@
|
|||
|
||||
#include "Instruction.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
class End : public Instruction {
|
||||
public:
|
||||
End(){
|
||||
End() {
|
||||
|
||||
}
|
||||
|
||||
CommandOp getCommand() const override{
|
||||
CommandOp getCommand() const override {
|
||||
return CommandOp::END;
|
||||
};
|
||||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
|
@ -48,7 +48,8 @@ namespace Instruction{
|
|||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> execute(AnalysisState& state) const override;
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
execute(AnalysisState &state) const override;
|
||||
|
||||
uint32_t reserved = 0;
|
||||
};
|
||||
|
|
|
@ -59,7 +59,6 @@ void Instruction::Init::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
data_add |= bytes[offset++];
|
||||
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
||||
|
@ -67,11 +66,11 @@ std::string Instruction::Init::toString() const {
|
|||
std::stringstream op;
|
||||
|
||||
op << "INIT INTO " << getAddressRegisterName(address, addressOffset);
|
||||
if(count > 1 && increment){
|
||||
if (count > 1 && increment) {
|
||||
op << " UNTIL " << getAddressRegisterName(address + count - 1, addressOffset);
|
||||
}
|
||||
op << " COUNT " << std::hex << std::setw(6) << std::setfill('0') << count;
|
||||
op << " INCREMENT " << std::dec << (uint32_t)increment;
|
||||
op << " INCREMENT " << std::dec << (uint32_t) increment;
|
||||
op << " DATA 0x" << std::hex << std::setw(8) << std::setfill('0') << data;
|
||||
op << " INC 0x" << std::hex << std::setw(8) << std::setfill('0') << data_add;
|
||||
|
||||
|
@ -82,7 +81,8 @@ std::vector<uint32_t> Instruction::Init::getPossibleBranches() const {
|
|||
return std::vector<uint32_t>{_endAddress};
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruction::Init::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::Init::execute(AnalysisState &state) const {
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
state.setRegister(address + (increment ? i : 0), data + data_add * i);
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
std::vector<uint8_t> Instruction::Init::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand() | (increment << 2) | addressOffset);
|
||||
bytes.emplace_back((uint8_t) getCommand() | (increment << 2) | addressOffset);
|
||||
|
||||
bytes.emplace_back((address >> 16) & 0xFF);
|
||||
bytes.emplace_back((address >> 8) & 0xFF);
|
||||
|
|
|
@ -29,18 +29,18 @@
|
|||
|
||||
#include "Instruction.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
class Init : public Instruction {
|
||||
public:
|
||||
Init(){
|
||||
Init() {
|
||||
|
||||
}
|
||||
|
||||
CommandOp getCommand() const override{
|
||||
CommandOp getCommand() const override {
|
||||
return CommandOp::INIT;
|
||||
};
|
||||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
|
@ -48,7 +48,8 @@ namespace Instruction{
|
|||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> execute(AnalysisState& state) const override;
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
execute(AnalysisState &state) const override;
|
||||
|
||||
|
||||
uint8_t addressOffset;
|
||||
|
|
|
@ -42,9 +42,10 @@
|
|||
#include "Wait.h"
|
||||
#include "End.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
|
||||
std::unique_ptr<Instruction> Instruction::Instruction::decodeInstructionFromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
|
||||
std::unique_ptr<Instruction>
|
||||
Instruction::Instruction::decodeInstructionFromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
|
||||
auto result = std::unique_ptr<Instruction>(nullptr);
|
||||
|
||||
CommandOp command = getCommandFromByte(bytes[offset]);
|
||||
|
@ -93,7 +94,7 @@ namespace Instruction{
|
|||
break;
|
||||
}
|
||||
|
||||
if(result != nullptr){
|
||||
if (result != nullptr) {
|
||||
result->fromBytes(offset, bytes);
|
||||
}
|
||||
|
||||
|
@ -101,33 +102,33 @@ namespace Instruction{
|
|||
}
|
||||
|
||||
Instruction::CommandOp Instruction::getCommandFromByte(uint8_t command) {
|
||||
if(((command >> 6) & 0b11) == 0b00){
|
||||
if (((command >> 6) & 0b11) == 0b00) {
|
||||
return CommandOp::WRITE;
|
||||
}else if(((command >> 6) & 0b11) == 0b01){
|
||||
} else if (((command >> 6) & 0b11) == 0b01) {
|
||||
return CommandOp::COPY;
|
||||
}else if(((command >> 3) & 0b11111) == 0b11000){
|
||||
} else if (((command >> 3) & 0b11111) == 0b11000) {
|
||||
return CommandOp::LOAD;
|
||||
}else if(((command >> 3) & 0b11111) == 0b11001){
|
||||
} else if (((command >> 3) & 0b11111) == 0b11001) {
|
||||
return CommandOp::INIT;
|
||||
}else if(((command >> 5) & 0b111) == 0b100){
|
||||
} else if (((command >> 5) & 0b111) == 0b100) {
|
||||
return CommandOp::CALC;
|
||||
}else if(((command >> 5) & 0b111) == 0b101){
|
||||
} else if (((command >> 5) & 0b111) == 0b101) {
|
||||
return CommandOp::CALC_IMM;
|
||||
}else if(((command >> 3) & 0b11111) == 0b11010){
|
||||
} else if (((command >> 3) & 0b11111) == 0b11010) {
|
||||
return CommandOp::BRANCH;
|
||||
}else if(((command >> 3) & 0b11111) == 0b11011){
|
||||
} else if (((command >> 3) & 0b11111) == 0b11011) {
|
||||
return CommandOp::POLL;
|
||||
}else if(((command >> 1) & 0b1111111) == 0b1110000){
|
||||
} else if (((command >> 1) & 0b1111111) == 0b1110000) {
|
||||
return CommandOp::LOOP;
|
||||
}else if(command == 0b11101000){
|
||||
} else if (command == 0b11101000) {
|
||||
return CommandOp::JUMP;
|
||||
}else if(((command >> 2) & 0b111111) == 0b111100){
|
||||
} else if (((command >> 2) & 0b111111) == 0b111100) {
|
||||
return CommandOp::RETURN;
|
||||
}else if(((command >> 2) & 0b111111) == 0b111110){
|
||||
} else if (((command >> 2) & 0b111111) == 0b111110) {
|
||||
return CommandOp::SET;
|
||||
}else if(command == 0xFE){
|
||||
} else if (command == 0xFE) {
|
||||
return CommandOp::WAIT;
|
||||
}else if(command == 0xFF){
|
||||
} else if (command == 0xFF) {
|
||||
return CommandOp::END;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,9 +34,9 @@
|
|||
#include <memory>
|
||||
#include "../AnalysisState.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
|
||||
class Instruction{
|
||||
class Instruction {
|
||||
protected:
|
||||
uint32_t _address;
|
||||
uint32_t _endAddress;
|
||||
|
@ -55,24 +55,25 @@ namespace Instruction{
|
|||
*/
|
||||
|
||||
enum class CommandOp : uint8_t {
|
||||
WRITE = 0b00000000,
|
||||
COPY = 0b01000000,
|
||||
LOAD = 0b11000000,
|
||||
INIT = 0b11001000,
|
||||
CALC = 0b10000000,
|
||||
WRITE = 0b00000000,
|
||||
COPY = 0b01000000,
|
||||
LOAD = 0b11000000,
|
||||
INIT = 0b11001000,
|
||||
CALC = 0b10000000,
|
||||
CALC_IMM = 0b10100000,
|
||||
BRANCH = 0b11010000,
|
||||
POLL = 0b11011000,
|
||||
LOOP = 0b11100000,
|
||||
JUMP = 0b11101000,
|
||||
POLL = 0b11011000,
|
||||
LOOP = 0b11100000,
|
||||
JUMP = 0b11101000,
|
||||
RETURN = 0b11110000,
|
||||
SET = 0b11111000,
|
||||
WAIT = 0xFE,
|
||||
END = 0xFF,
|
||||
SET = 0b11111000,
|
||||
WAIT = 0xFE,
|
||||
END = 0xFF,
|
||||
NOP = 0xFF
|
||||
};
|
||||
|
||||
static std::unique_ptr<Instruction> decodeInstructionFromBytes(uint32_t offset, const std::vector<uint8_t>& bytes);
|
||||
static std::unique_ptr<Instruction>
|
||||
decodeInstructionFromBytes(uint32_t offset, const std::vector<uint8_t> &bytes);
|
||||
|
||||
static CommandOp getCommandFromByte(uint8_t command);
|
||||
|
||||
|
@ -81,7 +82,7 @@ namespace Instruction{
|
|||
|
||||
}*/
|
||||
|
||||
virtual void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) = 0;
|
||||
virtual void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) = 0;
|
||||
|
||||
virtual std::vector<uint8_t> toBytes() const = 0;
|
||||
|
||||
|
@ -89,15 +90,16 @@ namespace Instruction{
|
|||
|
||||
virtual std::vector<uint32_t> getPossibleBranches() const = 0;
|
||||
|
||||
virtual std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> execute(AnalysisState& state) const = 0;
|
||||
virtual std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
execute(AnalysisState &state) const = 0;
|
||||
|
||||
virtual CommandOp getCommand() const = 0;
|
||||
|
||||
uint32_t getAddress() const{
|
||||
uint32_t getAddress() const {
|
||||
return _address;
|
||||
}
|
||||
|
||||
uint32_t getEndAddress() const{
|
||||
uint32_t getEndAddress() const {
|
||||
return _endAddress;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ void Instruction::Jump::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
jumpAddress |= bytes[offset++];
|
||||
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
||||
|
@ -55,7 +54,8 @@ std::vector<uint32_t> Instruction::Jump::getPossibleBranches() const {
|
|||
return std::vector<uint32_t>{jumpAddress};
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruction::Jump::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::Jump::execute(AnalysisState &state) const {
|
||||
state.current = jumpAddress;
|
||||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
|
@ -64,7 +64,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
std::vector<uint8_t> Instruction::Jump::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand());
|
||||
bytes.emplace_back((uint8_t) getCommand());
|
||||
|
||||
bytes.emplace_back((jumpAddress >> 16) & 0xFF);
|
||||
bytes.emplace_back((jumpAddress >> 8) & 0xFF);
|
||||
|
|
|
@ -29,18 +29,18 @@
|
|||
|
||||
#include "Instruction.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
class Jump : public Instruction {
|
||||
public:
|
||||
Jump(){
|
||||
Jump() {
|
||||
|
||||
}
|
||||
|
||||
CommandOp getCommand() const override{
|
||||
CommandOp getCommand() const override {
|
||||
return CommandOp::JUMP;
|
||||
};
|
||||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
|
@ -48,7 +48,8 @@ namespace Instruction{
|
|||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> execute(AnalysisState& state) const override;
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
execute(AnalysisState &state) const override;
|
||||
|
||||
uint32_t jumpAddress;
|
||||
};
|
||||
|
|
|
@ -49,7 +49,7 @@ void Instruction::Load::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
count |= bytes[offset++] << 8;
|
||||
count |= bytes[offset++];
|
||||
|
||||
for(uint32_t i = 0; i < count; ++i){
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
uint32_t entry = bytes[offset++] << 24;
|
||||
entry |= bytes[offset++] << 16;
|
||||
entry |= bytes[offset++] << 8;
|
||||
|
@ -58,15 +58,14 @@ void Instruction::Load::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
||||
std::string Instruction::Load::toString() const {
|
||||
std::stringstream op;
|
||||
|
||||
if(addressOffset == 0 && increment == 0 && address == (uint32_t)KnownRegisters::PCIE_MASTER_SPICO_FIRMWARE_SPECIAL_REGISTER){
|
||||
if (addressOffset == 0 && increment == 0 &&
|
||||
address == (uint32_t) KnownRegisters::PCIE_MASTER_SPICO_FIRMWARE_SPECIAL_REGISTER) {
|
||||
op << "LOAD PCIE_MASTER_SPICO_FIRMWARE DATA 0x";
|
||||
for (auto d : data) {
|
||||
op << std::hex << std::setw(8) << std::setfill('0') << d;
|
||||
|
@ -77,7 +76,8 @@ std::string Instruction::Load::toString() const {
|
|||
op << " SPICO_FW[" << std::hex << std::setw(4) << std::setfill('0') << i << "]";
|
||||
op << " = 0x" << std::hex << std::setw(3) << std::setfill('0') << fw.firmware[i] << "\n";
|
||||
}
|
||||
} else if(addressOffset == 0 && increment == 0 && address == (uint32_t)KnownRegisters::PCIE_BROADCAST_SERDES_FIRMWARE_SPECIAL_REGISTER){
|
||||
} else if (addressOffset == 0 && increment == 0 &&
|
||||
address == (uint32_t) KnownRegisters::PCIE_BROADCAST_SERDES_FIRMWARE_SPECIAL_REGISTER) {
|
||||
op << "LOAD PCIE_BROADCAST_SERDES_FIRMWARE DATA 0x";
|
||||
for (auto d : data) {
|
||||
op << std::hex << std::setw(8) << std::setfill('0') << d;
|
||||
|
@ -88,9 +88,9 @@ std::string Instruction::Load::toString() const {
|
|||
op << " SERDES_FW[" << std::hex << std::setw(4) << std::setfill('0') << i << "]";
|
||||
op << " = 0x" << std::hex << std::setw(3) << std::setfill('0') << fw.firmware[i] << "\n";
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
op << "LOAD INTO " << getAddressRegisterName(address, addressOffset);
|
||||
if(data.size() > 1 && increment){
|
||||
if (data.size() > 1 && increment) {
|
||||
op << " UNTIL " << getAddressRegisterName(address + data.size() - 1, addressOffset);
|
||||
}
|
||||
op << " INCREMENT " << std::dec << (uint32_t) increment;
|
||||
|
@ -99,9 +99,10 @@ std::string Instruction::Load::toString() const {
|
|||
op << std::hex << std::setw(8) << std::setfill('0') << d;
|
||||
}
|
||||
|
||||
if(data.size() > 1){
|
||||
if (data.size() > 1) {
|
||||
for (uint32_t i = 0; i < data.size(); ++i) {
|
||||
op << "\n " << getAddressRegisterName(address + (increment ? i : 0)) << " = 0x" << std::hex << std::setw(8) << std::setfill('0') << data[i];
|
||||
op << "\n " << getAddressRegisterName(address + (increment ? i : 0)) << " = 0x" << std::hex
|
||||
<< std::setw(8) << std::setfill('0') << data[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -114,13 +115,16 @@ std::vector<uint32_t> Instruction::Load::getPossibleBranches() const {
|
|||
return std::vector<uint32_t>{_endAddress};
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruction::Load::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::Load::execute(AnalysisState &state) const {
|
||||
|
||||
if(addressOffset == 0 && increment == 0 && address == (uint32_t)KnownRegisters::PCIE_MASTER_SPICO_FIRMWARE_SPECIAL_REGISTER){
|
||||
if (addressOffset == 0 && increment == 0 &&
|
||||
address == (uint32_t) KnownRegisters::PCIE_MASTER_SPICO_FIRMWARE_SPECIAL_REGISTER) {
|
||||
state.pciSPICOFirmware = SmallFirmwareFormat::fromBSMLoad(data, 0);
|
||||
} else if(addressOffset == 0 && increment == 0 && address == (uint32_t)KnownRegisters::PCIE_BROADCAST_SERDES_FIRMWARE_SPECIAL_REGISTER){
|
||||
} else if (addressOffset == 0 && increment == 0 &&
|
||||
address == (uint32_t) KnownRegisters::PCIE_BROADCAST_SERDES_FIRMWARE_SPECIAL_REGISTER) {
|
||||
state.pciSerDesFirmware = SmallFirmwareFormat::fromBSMLoad(data, 0);
|
||||
}else{
|
||||
} else {
|
||||
for (uint32_t i = 0; i < data.size(); ++i) {
|
||||
state.setRegister(address + (increment ? i : 0), data[i]);
|
||||
}
|
||||
|
@ -134,7 +138,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
std::vector<uint8_t> Instruction::Load::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand() | (increment << 2) | addressOffset);
|
||||
bytes.emplace_back((uint8_t) getCommand() | (increment << 2) | addressOffset);
|
||||
|
||||
bytes.emplace_back((address >> 16) & 0xFF);
|
||||
bytes.emplace_back((address >> 8) & 0xFF);
|
||||
|
|
|
@ -29,18 +29,18 @@
|
|||
|
||||
#include "Instruction.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
class Load : public Instruction {
|
||||
public:
|
||||
Load(){
|
||||
Load() {
|
||||
|
||||
}
|
||||
|
||||
CommandOp getCommand() const override{
|
||||
CommandOp getCommand() const override {
|
||||
return CommandOp::LOAD;
|
||||
};
|
||||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
|
@ -48,7 +48,8 @@ namespace Instruction{
|
|||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> execute(AnalysisState& state) const override;
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
execute(AnalysisState &state) const override;
|
||||
|
||||
|
||||
uint8_t addressOffset;
|
||||
|
|
|
@ -42,13 +42,13 @@ void Instruction::Loop::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
jumpAddress |= bytes[offset++];
|
||||
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
||||
std::string Instruction::Loop::toString() const {
|
||||
std::stringstream op;
|
||||
op << "LOOP IF " << getRegisterName(static_cast<KnownRegisters>((uint32_t)KnownRegisters::BSM_COUNTER_0 + counter)) << " != 0 JUMP 0x" << std::hex << std::setw(6) << std::setfill('0') << jumpAddress;
|
||||
op << "LOOP IF " << getRegisterName(static_cast<KnownRegisters>((uint32_t) KnownRegisters::BSM_COUNTER_0 + counter))
|
||||
<< " != 0 JUMP 0x" << std::hex << std::setw(6) << std::setfill('0') << jumpAddress;
|
||||
return op.str();
|
||||
}
|
||||
|
||||
|
@ -56,18 +56,19 @@ std::vector<uint32_t> Instruction::Loop::getPossibleBranches() const {
|
|||
return std::vector<uint32_t>{_endAddress, jumpAddress};
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruction::Loop::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::Loop::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> branches;
|
||||
|
||||
uint32_t counterAddress = (uint32_t)KnownRegisters::BSM_COUNTER_0 + counter;
|
||||
uint32_t counterAddress = (uint32_t) KnownRegisters::BSM_COUNTER_0 + counter;
|
||||
|
||||
if(state.getRegister(counterAddress) == 0){
|
||||
if (state.getRegister(counterAddress) == 0) {
|
||||
state.current = _endAddress;
|
||||
|
||||
std::unordered_map<uint32_t, uint32_t> branchedState;
|
||||
branchedState[counterAddress] = 1;
|
||||
branches.emplace_back(jumpAddress, std::move(branchedState));
|
||||
}else{
|
||||
} else {
|
||||
state.setRegister(counterAddress, state.getRegister(counterAddress) - 1);
|
||||
state.current = jumpAddress;
|
||||
|
||||
|
@ -82,7 +83,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
std::vector<uint8_t> Instruction::Loop::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand() | counter);
|
||||
bytes.emplace_back((uint8_t) getCommand() | counter);
|
||||
|
||||
bytes.emplace_back((jumpAddress >> 16) & 0xFF);
|
||||
bytes.emplace_back((jumpAddress >> 8) & 0xFF);
|
||||
|
|
|
@ -29,18 +29,18 @@
|
|||
|
||||
#include "Instruction.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
class Loop : public Instruction {
|
||||
public:
|
||||
Loop(){
|
||||
Loop() {
|
||||
|
||||
}
|
||||
|
||||
CommandOp getCommand() const override{
|
||||
CommandOp getCommand() const override {
|
||||
return CommandOp::LOOP;
|
||||
};
|
||||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
|
@ -48,7 +48,8 @@ namespace Instruction{
|
|||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> execute(AnalysisState& state) const override;
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
execute(AnalysisState &state) const override;
|
||||
|
||||
|
||||
uint8_t counter;
|
||||
|
|
|
@ -65,19 +65,21 @@ void Instruction::Poll::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
jumpAddress |= bytes[offset++];
|
||||
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
||||
std::string Instruction::Poll::toString() const {
|
||||
std::stringstream op;
|
||||
op << "POLL IF (" << getAddressRegisterName(address, addressOffset) << " & 0x" << std::hex << std::setw(8) << std::setfill('0') << mask << ")";
|
||||
if(equality){
|
||||
op << "POLL IF (" << getAddressRegisterName(address, addressOffset) << " & 0x" << std::hex << std::setw(8)
|
||||
<< std::setfill('0') << mask << ")";
|
||||
if (equality) {
|
||||
op << " != ";
|
||||
}else{
|
||||
} else {
|
||||
op << " == ";
|
||||
}
|
||||
op << "0x" << std::hex << std::setw(8) << std::setfill('0') << value << " WAIT " << std::dec << retryInterval << " MAX " << std::dec << maxRetry << " EXCEED JUMP 0x" << std::hex << std::setw(6) << std::setfill('0') << jumpAddress;
|
||||
op << "0x" << std::hex << std::setw(8) << std::setfill('0') << value << " WAIT " << std::dec << retryInterval
|
||||
<< " MAX " << std::dec << maxRetry << " EXCEED JUMP 0x" << std::hex << std::setw(6) << std::setfill('0')
|
||||
<< jumpAddress;
|
||||
|
||||
return op.str();
|
||||
}
|
||||
|
@ -86,22 +88,25 @@ std::vector<uint32_t> Instruction::Poll::getPossibleBranches() const {
|
|||
return std::vector<uint32_t>{_endAddress, jumpAddress};
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruction::Poll::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::Poll::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> branches;
|
||||
|
||||
uint32_t memoryOffset = state.getAddressOffset(addressOffset);
|
||||
|
||||
if((state.getRegister(memoryOffset + address) & mask) == value){
|
||||
if ((state.getRegister(memoryOffset + address) & mask) == value) {
|
||||
state.current = equality ? _endAddress : jumpAddress;
|
||||
|
||||
std::unordered_map<uint32_t, uint32_t> branchedState;
|
||||
branchedState[memoryOffset + address] = state.getRegister(memoryOffset + address) | (equality ? value : ~value & mask);
|
||||
branchedState[memoryOffset + address] =
|
||||
state.getRegister(memoryOffset + address) | (equality ? value : ~value & mask);
|
||||
branches.emplace_back(equality ? jumpAddress : _endAddress, std::move(branchedState));
|
||||
}else{
|
||||
} else {
|
||||
state.current = equality ? jumpAddress : _endAddress;
|
||||
|
||||
std::unordered_map<uint32_t, uint32_t> branchedState;
|
||||
branchedState[memoryOffset + address] = state.getRegister(memoryOffset + address) | (equality ? ~value & mask : value);
|
||||
branchedState[memoryOffset + address] =
|
||||
state.getRegister(memoryOffset + address) | (equality ? ~value & mask : value);
|
||||
branches.emplace_back(equality ? _endAddress : jumpAddress, std::move(branchedState));
|
||||
}
|
||||
|
||||
|
@ -111,7 +116,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
std::vector<uint8_t> Instruction::Poll::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand() | (equality << 2) | addressOffset);
|
||||
bytes.emplace_back((uint8_t) getCommand() | (equality << 2) | addressOffset);
|
||||
|
||||
bytes.emplace_back((address >> 16) & 0xFF);
|
||||
bytes.emplace_back((address >> 8) & 0xFF);
|
||||
|
|
|
@ -29,18 +29,18 @@
|
|||
|
||||
#include "Instruction.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
class Poll : public Instruction {
|
||||
public:
|
||||
Poll(){
|
||||
Poll() {
|
||||
|
||||
}
|
||||
|
||||
CommandOp getCommand() const override{
|
||||
CommandOp getCommand() const override {
|
||||
return CommandOp::POLL;
|
||||
};
|
||||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
|
@ -48,7 +48,8 @@ namespace Instruction{
|
|||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> execute(AnalysisState& state) const override;
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
execute(AnalysisState &state) const override;
|
||||
|
||||
|
||||
uint8_t addressOffset;
|
||||
|
|
|
@ -42,7 +42,6 @@ void Instruction::Return::fromBytes(uint32_t offset, const std::vector<uint8_t>
|
|||
address |= bytes[offset++];
|
||||
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
||||
|
@ -57,7 +56,8 @@ std::vector<uint32_t> Instruction::Return::getPossibleBranches() const {
|
|||
return std::vector<uint32_t>();
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruction::Return::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::Return::execute(AnalysisState &state) const {
|
||||
uint32_t memoryOffset = state.getAddressOffset(addressOffset);
|
||||
|
||||
uint32_t jumpAddress = state.getRegister(memoryOffset + address);
|
||||
|
@ -70,7 +70,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
std::vector<uint8_t> Instruction::Return::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand() | addressOffset);
|
||||
bytes.emplace_back((uint8_t) getCommand() | addressOffset);
|
||||
|
||||
bytes.emplace_back((address >> 16) & 0xFF);
|
||||
bytes.emplace_back((address >> 8) & 0xFF);
|
||||
|
|
|
@ -29,18 +29,18 @@
|
|||
|
||||
#include "Instruction.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
class Return : public Instruction {
|
||||
public:
|
||||
Return(){
|
||||
Return() {
|
||||
|
||||
}
|
||||
|
||||
CommandOp getCommand() const override{
|
||||
CommandOp getCommand() const override {
|
||||
return CommandOp::RETURN;
|
||||
};
|
||||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
|
@ -48,7 +48,8 @@ namespace Instruction{
|
|||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> execute(AnalysisState& state) const override;
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
execute(AnalysisState &state) const override;
|
||||
|
||||
uint8_t addressOffset;
|
||||
uint32_t address;
|
||||
|
|
|
@ -52,13 +52,14 @@ void Instruction::Set::fromBytes(uint32_t offset, const std::vector<uint8_t> &by
|
|||
mask |= bytes[offset++];
|
||||
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
||||
std::string Instruction::Set::toString() const {
|
||||
std::stringstream op;
|
||||
op << "SET " << getAddressRegisterName(address, addressOffset) << " = (" << getAddressRegisterName(address, addressOffset) << " & ~0x" << std::hex << std::setw(8) << std::setfill('0') << mask << ") | " << "0x" << std::hex << std::setw(8) << std::setfill('0') << value;
|
||||
op << "SET " << getAddressRegisterName(address, addressOffset) << " = ("
|
||||
<< getAddressRegisterName(address, addressOffset) << " & ~0x" << std::hex << std::setw(8) << std::setfill('0')
|
||||
<< mask << ") | " << "0x" << std::hex << std::setw(8) << std::setfill('0') << value;
|
||||
return op.str();
|
||||
}
|
||||
|
||||
|
@ -66,7 +67,8 @@ std::vector<uint32_t> Instruction::Set::getPossibleBranches() const {
|
|||
return std::vector<uint32_t>{_endAddress};
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruction::Set::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::Set::execute(AnalysisState &state) const {
|
||||
uint32_t memoryOffset = state.getAddressOffset(addressOffset);
|
||||
|
||||
state.setRegister(memoryOffset + address, (state.getRegister(memoryOffset + address) & ~mask) | value);
|
||||
|
@ -79,7 +81,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
std::vector<uint8_t> Instruction::Set::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand() | addressOffset);
|
||||
bytes.emplace_back((uint8_t) getCommand() | addressOffset);
|
||||
|
||||
bytes.emplace_back((address >> 16) & 0xFF);
|
||||
bytes.emplace_back((address >> 8) & 0xFF);
|
||||
|
|
|
@ -29,18 +29,18 @@
|
|||
|
||||
#include "Instruction.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
class Set : public Instruction {
|
||||
public:
|
||||
Set(){
|
||||
Set() {
|
||||
|
||||
}
|
||||
|
||||
CommandOp getCommand() const override{
|
||||
CommandOp getCommand() const override {
|
||||
return CommandOp::SET;
|
||||
};
|
||||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
|
@ -48,7 +48,8 @@ namespace Instruction{
|
|||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> execute(AnalysisState& state) const override;
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
execute(AnalysisState &state) const override;
|
||||
|
||||
uint8_t addressOffset;
|
||||
uint32_t address;
|
||||
|
|
|
@ -40,7 +40,6 @@ void Instruction::Wait::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
time |= bytes[offset++];
|
||||
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
||||
|
@ -55,7 +54,8 @@ std::vector<uint32_t> Instruction::Wait::getPossibleBranches() const {
|
|||
return std::vector<uint32_t>{_endAddress};
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruction::Wait::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::Wait::execute(AnalysisState &state) const {
|
||||
//How to wait?
|
||||
|
||||
state.current = _endAddress;
|
||||
|
@ -66,7 +66,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
std::vector<uint8_t> Instruction::Wait::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand());
|
||||
bytes.emplace_back((uint8_t) getCommand());
|
||||
|
||||
bytes.emplace_back((time >> 16) & 0xFF);
|
||||
bytes.emplace_back((time >> 8) & 0xFF);
|
||||
|
|
|
@ -29,18 +29,18 @@
|
|||
|
||||
#include "Instruction.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
class Wait : public Instruction {
|
||||
public:
|
||||
Wait(){
|
||||
Wait() {
|
||||
|
||||
}
|
||||
|
||||
CommandOp getCommand() const override{
|
||||
CommandOp getCommand() const override {
|
||||
return CommandOp::WAIT;
|
||||
};
|
||||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
|
@ -48,7 +48,8 @@ namespace Instruction{
|
|||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> execute(AnalysisState& state) const override;
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
execute(AnalysisState &state) const override;
|
||||
|
||||
uint32_t time;
|
||||
};
|
||||
|
|
|
@ -42,7 +42,7 @@ void Instruction::Write::fromBytes(uint32_t offset, const std::vector<uint8_t> &
|
|||
address |= bytes[offset++] << 8;
|
||||
address |= bytes[offset++];
|
||||
|
||||
for(uint32_t i = 0; i < count; ++i){
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
uint32_t entry = bytes[offset++] << 24;
|
||||
entry |= bytes[offset++] << 16;
|
||||
entry |= bytes[offset++] << 8;
|
||||
|
@ -51,8 +51,6 @@ void Instruction::Write::fromBytes(uint32_t offset, const std::vector<uint8_t> &
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
||||
|
@ -70,10 +68,11 @@ std::vector<uint32_t> Instruction::Write::getPossibleBranches() const {
|
|||
return std::vector<uint32_t>{_endAddress};
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruction::Write::execute(AnalysisState &state) const {
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
Instruction::Write::execute(AnalysisState &state) const {
|
||||
auto memoryOffset = state.getAddressOffset(addressOffset);
|
||||
|
||||
for(uint32_t i = 0; i < data.size(); ++i){
|
||||
for (uint32_t i = 0; i < data.size(); ++i) {
|
||||
state.setRegister(memoryOffset + address + i, data[i]);
|
||||
}
|
||||
|
||||
|
@ -85,7 +84,7 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
std::vector<uint8_t> Instruction::Write::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand() | ((data.size() - 1) << 2) | addressOffset);
|
||||
bytes.emplace_back((uint8_t) getCommand() | ((data.size() - 1) << 2) | addressOffset);
|
||||
|
||||
bytes.emplace_back((address >> 16) & 0xFF);
|
||||
bytes.emplace_back((address >> 8) & 0xFF);
|
||||
|
|
|
@ -31,22 +31,24 @@
|
|||
|
||||
#include "Instruction.h"
|
||||
|
||||
namespace Instruction{
|
||||
namespace Instruction {
|
||||
class Write : public Instruction {
|
||||
public:
|
||||
Write(uint32_t address, uint8_t addressOffset, std::vector<uint32_t> data) : address(address), addressOffset(addressOffset), data(std::move(data)){
|
||||
Write(uint32_t address, uint8_t addressOffset, std::vector<uint32_t> data) : address(address),
|
||||
addressOffset(addressOffset),
|
||||
data(std::move(data)) {
|
||||
|
||||
}
|
||||
|
||||
Write(){
|
||||
Write() {
|
||||
|
||||
}
|
||||
|
||||
CommandOp getCommand() const override{
|
||||
CommandOp getCommand() const override {
|
||||
return CommandOp::WRITE;
|
||||
};
|
||||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
|
@ -54,7 +56,8 @@ namespace Instruction{
|
|||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> execute(AnalysisState& state) const override;
|
||||
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
|
||||
execute(AnalysisState &state) const override;
|
||||
|
||||
|
||||
uint8_t addressOffset;
|
||||
|
|
283
src/main.cpp
283
src/main.cpp
|
@ -35,35 +35,38 @@
|
|||
#include "Registers.h"
|
||||
#include "instructions/Load.h"
|
||||
|
||||
void decodeImage(const std::string& fileName){
|
||||
void decodeImage(const std::string &fileName) {
|
||||
|
||||
std::ifstream image(fileName);
|
||||
if(image.is_open()){
|
||||
if (image.is_open()) {
|
||||
std::vector<uint8_t> bytes;
|
||||
while(!image.eof()){
|
||||
while (!image.eof()) {
|
||||
bytes.push_back(image.get());
|
||||
}
|
||||
auto imageObject = ImageFormat::fromBytes(bytes);
|
||||
|
||||
for(auto& k : imageObject.getBootConfig().getAllEntries()){
|
||||
for (auto &k : imageObject.getBootConfig().getAllEntries()) {
|
||||
std::cout << k << "\n";
|
||||
}
|
||||
|
||||
uint32_t prevAddress = 0;
|
||||
for(const auto& entry : imageObject.getInstructions()){
|
||||
const auto& instruction = entry.second;
|
||||
if(instruction->getAddress() < prevAddress){
|
||||
std::cout << "====== DECODE ERROR? ========== " << std::hex << std::setw(8) << std::setfill('0') << prevAddress << " - " << std::hex << std::setw(8) << std::setfill('0') << instruction->getAddress() << "\n";
|
||||
}else if((instruction->getAddress() - prevAddress) >= 4 && (instruction->getAddress() - prevAddress) < 1024){
|
||||
for(uint32_t addr = prevAddress; addr < instruction->getAddress(); addr += 4){
|
||||
for (const auto &entry : imageObject.getInstructions()) {
|
||||
const auto &instruction = entry.second;
|
||||
if (instruction->getAddress() < prevAddress) {
|
||||
std::cout << "====== DECODE ERROR? ========== " << std::hex << std::setw(8) << std::setfill('0')
|
||||
<< prevAddress << " - " << std::hex << std::setw(8) << std::setfill('0')
|
||||
<< instruction->getAddress() << "\n";
|
||||
} else if ((instruction->getAddress() - prevAddress) >= 4 &&
|
||||
(instruction->getAddress() - prevAddress) < 1024) {
|
||||
for (uint32_t addr = prevAddress; addr < instruction->getAddress(); addr += 4) {
|
||||
std::stringstream op;
|
||||
std::string printable;
|
||||
op << std::hex << std::setw(8) << std::setfill('0') << addr << ": ";
|
||||
for(uint32_t i = 0; i < 4; ++i){
|
||||
op << std::hex << std::setw(2) << std::setfill('0') << (uint32_t)bytes[addr + i];
|
||||
if(bytes[addr + i] >= 0x20 && bytes[addr + i] < 0x7F){
|
||||
for (uint32_t i = 0; i < 4; ++i) {
|
||||
op << std::hex << std::setw(2) << std::setfill('0') << (uint32_t) bytes[addr + i];
|
||||
if (bytes[addr + i] >= 0x20 && bytes[addr + i] < 0x7F) {
|
||||
printable += bytes[addr + i];
|
||||
}else{
|
||||
} else {
|
||||
printable += ".";
|
||||
}
|
||||
}
|
||||
|
@ -71,8 +74,10 @@ void decodeImage(const std::string& fileName){
|
|||
|
||||
std::cout << op.str();
|
||||
}
|
||||
}else if((instruction->getAddress() - prevAddress) >= 1024){
|
||||
std::cout << "================ " << std::hex << std::setw(8) << std::setfill('0') << prevAddress << " - " << std::hex << std::setw(8) << std::setfill('0') << instruction->getAddress() << "\n";
|
||||
} else if ((instruction->getAddress() - prevAddress) >= 1024) {
|
||||
std::cout << "================ " << std::hex << std::setw(8) << std::setfill('0') << prevAddress
|
||||
<< " - " << std::hex << std::setw(8) << std::setfill('0') << instruction->getAddress()
|
||||
<< "\n";
|
||||
}
|
||||
std::cout << std::hex << std::setw(8) << std::setfill('0') << instruction->getAddress() << ": ";
|
||||
std::cout << instruction->toString() << "\n";
|
||||
|
@ -81,19 +86,20 @@ void decodeImage(const std::string& fileName){
|
|||
}
|
||||
}
|
||||
|
||||
void patchImage(const std::string& originalImage, const std::string& settingsFile, const std::string& patchedImageFile){
|
||||
void
|
||||
patchImage(const std::string &originalImage, const std::string &settingsFile, const std::string &patchedImageFile) {
|
||||
std::ifstream image(originalImage);
|
||||
if(image.is_open()) {
|
||||
if (image.is_open()) {
|
||||
std::vector<uint8_t> bytes;
|
||||
while (!image.eof()) {
|
||||
bytes.push_back(image.get());
|
||||
}
|
||||
auto imageObject = ImageFormat::fromBytes(bytes);
|
||||
|
||||
Configuration& config = imageObject.getModifiableBootConfig();
|
||||
Configuration &config = imageObject.getModifiableBootConfig();
|
||||
|
||||
std::ifstream settings(settingsFile);
|
||||
if(settings.is_open()) {
|
||||
if (settings.is_open()) {
|
||||
|
||||
std::string line;
|
||||
while (!settings.eof()) {
|
||||
|
@ -103,12 +109,15 @@ void patchImage(const std::string& originalImage, const std::string& settingsFil
|
|||
|
||||
//Do patch
|
||||
|
||||
if(imageObject.imageSignature.find("Image Generated with rrcBig_02.22. EEPROM Image Version: 0x0222 PCIe Master SPICO FW Version: 0x10130001 PCIe SerDes SPICO FW Version: 0x30550043") == std::string::npos){
|
||||
std::cout << "Could not find supported generation signature on original image. Patching will not proceed.\n";
|
||||
if (imageObject.imageSignature.find(
|
||||
"Image Generated with rrcBig_02.22. EEPROM Image Version: 0x0222 PCIe Master SPICO FW Version: 0x10130001 PCIe SerDes SPICO FW Version: 0x30550043") ==
|
||||
std::string::npos) {
|
||||
std::cout
|
||||
<< "Could not find supported generation signature on original image. Patching will not proceed.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if(imageObject.imageSignature.find("rrcSmall") == std::string::npos){
|
||||
if (imageObject.imageSignature.find("rrcSmall") == std::string::npos) {
|
||||
imageObject.imageSignature += " :: Patched by rrcSmall :: git.gammaspectra.live/FM10K/rrcSmall";
|
||||
}
|
||||
|
||||
|
@ -186,31 +195,38 @@ void patchImage(const std::string& originalImage, const std::string& settingsFil
|
|||
// 0x93f0 LOAD 1 = 0x000f000a PCIE_CLKMON_TOLERANCE_CFG = value
|
||||
// 0x93fc LOAD 1 = 0x000a03e8 PCIE_CLKMON_DEADLINES_CFG = value
|
||||
|
||||
auto baseOffsets = std::vector<uint32_t>{imageObject.getHeader().baseAddress, (uint32_t) imageObject.getHeader().baseAddress + 0x40000}; //Target first and second bank
|
||||
auto baseOffsets = std::vector<uint32_t>{imageObject.getHeader().baseAddress,
|
||||
(uint32_t) imageObject.getHeader().baseAddress +
|
||||
0x40000}; //Target first and second bank
|
||||
|
||||
{
|
||||
auto entry = config.getEntry("api.platform.config.switch.0.bootCfg.mgmtPep");
|
||||
if(entry.type == Configuration::ConfigurationNode::Type::ValueInt && !entry.value.empty()){
|
||||
if (entry.type == Configuration::ConfigurationNode::Type::ValueInt && !entry.value.empty()) {
|
||||
std::cout << "Patching bootCfg.mgmtPep and bootCfg.pep.bar4Allowed\n";
|
||||
auto value = entry.getInteger();
|
||||
for(auto baseOffset : baseOffsets){
|
||||
auto& instruction = imageObject.findInstructionByAddress(baseOffset + 0x91f0);
|
||||
if(instruction != nullptr && instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD){
|
||||
auto& load = reinterpret_cast<std::unique_ptr<Instruction::Load>&>(instruction);
|
||||
if(load->address == (uint32_t)getScratchRegister(0x02e) && load->data.size() == 9){
|
||||
for(uint32_t pepOffset = 0; pepOffset < 9; ++pepOffset){
|
||||
for (auto baseOffset : baseOffsets) {
|
||||
auto &instruction = imageObject.findInstructionByAddress(baseOffset + 0x91f0);
|
||||
if (instruction != nullptr &&
|
||||
instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
auto &load = reinterpret_cast<std::unique_ptr<Instruction::Load> &>(instruction);
|
||||
if (load->address == (uint32_t) getScratchRegister(0x02e) && load->data.size() == 9) {
|
||||
for (uint32_t pepOffset = 0; pepOffset < 9; ++pepOffset) {
|
||||
std::stringstream key;
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset << ".bar4Allowed";
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset
|
||||
<< ".bar4Allowed";
|
||||
auto testEntry = config.getEntry(key.str());
|
||||
bool bar4allowed = true;
|
||||
if(testEntry.type == Configuration::ConfigurationNode::Type::ValueBool && !testEntry.value.empty()) {
|
||||
if (testEntry.type == Configuration::ConfigurationNode::Type::ValueBool &&
|
||||
!testEntry.value.empty()) {
|
||||
bar4allowed = testEntry.getBool();
|
||||
}
|
||||
|
||||
|
||||
load->data[pepOffset] = bar4allowed && (pepOffset == value || value == -1);
|
||||
//std::cout << " Patched PEP " << std::dec << pepOffset << " = 0x" << std::hex << std::setw(8) << std::setfill('0') << load->data[pepOffset] << " @ " << std::hex << std::setw(8) << std::setfill('0') << instruction->getAddress() << "\n";
|
||||
std::cout << " Patched PEP " << std::dec << pepOffset << " = " << (load->data[pepOffset] ? "true" : "false") << " @ " << std::hex << std::setw(6) << std::setfill('0') << instruction->getAddress() << "\n";
|
||||
std::cout << " Patched PEP " << std::dec << pepOffset << " = "
|
||||
<< (load->data[pepOffset] ? "true" : "false") << " @ " << std::hex
|
||||
<< std::setw(6) << std::setfill('0') << instruction->getAddress() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -219,24 +235,29 @@ void patchImage(const std::string& originalImage, const std::string& settingsFil
|
|||
}
|
||||
|
||||
{
|
||||
for(auto baseOffset : baseOffsets){
|
||||
auto& instruction = imageObject.findInstructionByAddress(baseOffset + 0x9230);
|
||||
if(instruction != nullptr && instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
for (auto baseOffset : baseOffsets) {
|
||||
auto &instruction = imageObject.findInstructionByAddress(baseOffset + 0x9230);
|
||||
if (instruction != nullptr &&
|
||||
instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
auto &load = reinterpret_cast<std::unique_ptr<Instruction::Load> &>(instruction);
|
||||
if (load->address == (uint32_t) getScratchRegister(0x049) && load->data.size() == 9) {
|
||||
for(uint32_t pepOffset = 0; pepOffset < 9; ++pepOffset){
|
||||
for (uint32_t pepOffset = 0; pepOffset < 9; ++pepOffset) {
|
||||
std::stringstream key;
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset << ".vendorId";
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset
|
||||
<< ".vendorId";
|
||||
auto vendorIdEntry = config.getEntry(key.str());
|
||||
if(vendorIdEntry.type == Configuration::ConfigurationNode::Type::ValueInt && !vendorIdEntry.value.empty()) {
|
||||
if (vendorIdEntry.type == Configuration::ConfigurationNode::Type::ValueInt &&
|
||||
!vendorIdEntry.value.empty()) {
|
||||
uint16_t vendorId = vendorIdEntry.getInteger();
|
||||
key.str("");
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset << ".deviceId";
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset
|
||||
<< ".deviceId";
|
||||
auto deviceIdEntry = config.getEntry(key.str());
|
||||
if(deviceIdEntry.type == Configuration::ConfigurationNode::Type::ValueInt && !deviceIdEntry.value.empty()) {
|
||||
if (deviceIdEntry.type == Configuration::ConfigurationNode::Type::ValueInt &&
|
||||
!deviceIdEntry.value.empty()) {
|
||||
uint16_t deviceId = deviceIdEntry.getInteger();
|
||||
|
||||
load->data[pepOffset] = ((uint32_t)deviceId << 16) | vendorId;
|
||||
load->data[pepOffset] = ((uint32_t) deviceId << 16) | vendorId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -246,24 +267,29 @@ void patchImage(const std::string& originalImage, const std::string& settingsFil
|
|||
}
|
||||
|
||||
{
|
||||
for(auto baseOffset : baseOffsets){
|
||||
auto& instruction = imageObject.findInstructionByAddress(baseOffset + 0x9260);
|
||||
if(instruction != nullptr && instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
for (auto baseOffset : baseOffsets) {
|
||||
auto &instruction = imageObject.findInstructionByAddress(baseOffset + 0x9260);
|
||||
if (instruction != nullptr &&
|
||||
instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
auto &load = reinterpret_cast<std::unique_ptr<Instruction::Load> &>(instruction);
|
||||
if (load->address == (uint32_t) getScratchRegister(0x052) && load->data.size() == 9) {
|
||||
for(uint32_t pepOffset = 0; pepOffset < 9; ++pepOffset){
|
||||
for (uint32_t pepOffset = 0; pepOffset < 9; ++pepOffset) {
|
||||
std::stringstream key;
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset << ".subVendorId";
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset
|
||||
<< ".subVendorId";
|
||||
auto subVendorIdEntry = config.getEntry(key.str());
|
||||
if(subVendorIdEntry.type == Configuration::ConfigurationNode::Type::ValueInt && !subVendorIdEntry.value.empty()) {
|
||||
if (subVendorIdEntry.type == Configuration::ConfigurationNode::Type::ValueInt &&
|
||||
!subVendorIdEntry.value.empty()) {
|
||||
uint16_t subVendorId = subVendorIdEntry.getInteger();
|
||||
key.str("");
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset << ".subDeviceId";
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset
|
||||
<< ".subDeviceId";
|
||||
auto subDeviceIdEntry = config.getEntry(key.str());
|
||||
if(subDeviceIdEntry.type == Configuration::ConfigurationNode::Type::ValueInt && !subDeviceIdEntry.value.empty()) {
|
||||
if (subDeviceIdEntry.type == Configuration::ConfigurationNode::Type::ValueInt &&
|
||||
!subDeviceIdEntry.value.empty()) {
|
||||
uint16_t subDeviceId = subDeviceIdEntry.getInteger();
|
||||
|
||||
load->data[pepOffset] = ((uint32_t)subDeviceId << 16) | subVendorId;
|
||||
load->data[pepOffset] = ((uint32_t) subDeviceId << 16) | subVendorId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -273,19 +299,23 @@ void patchImage(const std::string& originalImage, const std::string& settingsFil
|
|||
}
|
||||
|
||||
{
|
||||
for(auto baseOffset : baseOffsets){
|
||||
auto& instruction = imageObject.findInstructionByAddress(baseOffset + 0x9130);
|
||||
if(instruction != nullptr && instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
for (auto baseOffset : baseOffsets) {
|
||||
auto &instruction = imageObject.findInstructionByAddress(baseOffset + 0x9130);
|
||||
if (instruction != nullptr &&
|
||||
instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
auto &load = reinterpret_cast<std::unique_ptr<Instruction::Load> &>(instruction);
|
||||
if (load->address == (uint32_t) getScratchRegister(0x01c) && load->data.size() == 9) {
|
||||
for(uint32_t pepOffset = 0; pepOffset < 9; ++pepOffset){
|
||||
for (uint32_t pepOffset = 0; pepOffset < 9; ++pepOffset) {
|
||||
std::stringstream key;
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset << ".numberOfLanes";
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset
|
||||
<< ".numberOfLanes";
|
||||
auto entry = config.getEntry(key.str());
|
||||
if(entry.type == Configuration::ConfigurationNode::Type::ValueInt && !entry.value.empty()) {
|
||||
if (entry.type == Configuration::ConfigurationNode::Type::ValueInt &&
|
||||
!entry.value.empty()) {
|
||||
uint32_t value = entry.getInteger();
|
||||
if(load->data[pepOffset] != value) {
|
||||
std::cout << "Patching " << key.str() << " = " << std::dec << load->data[pepOffset]
|
||||
if (load->data[pepOffset] != value) {
|
||||
std::cout << "Patching " << key.str() << " = " << std::dec
|
||||
<< load->data[pepOffset]
|
||||
<< " -> " << std::dec << value << " @ " << std::hex << std::setw(6)
|
||||
<< std::setfill('0') << instruction->getAddress() << "\n";
|
||||
}
|
||||
|
@ -298,19 +328,22 @@ void patchImage(const std::string& originalImage, const std::string& settingsFil
|
|||
}
|
||||
|
||||
{
|
||||
for(auto baseOffset : baseOffsets){
|
||||
auto& instruction = imageObject.findInstructionByAddress(baseOffset + 0x92f0);
|
||||
if(instruction != nullptr && instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
for (auto baseOffset : baseOffsets) {
|
||||
auto &instruction = imageObject.findInstructionByAddress(baseOffset + 0x92f0);
|
||||
if (instruction != nullptr &&
|
||||
instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
auto &load = reinterpret_cast<std::unique_ptr<Instruction::Load> &>(instruction);
|
||||
if (load->address == (uint32_t) getScratchRegister(0x075) && load->data.size() == 9) {
|
||||
for(uint32_t pepOffset = 0; pepOffset < 9; ++pepOffset){
|
||||
for (uint32_t pepOffset = 0; pepOffset < 9; ++pepOffset) {
|
||||
std::stringstream key;
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset << ".gen";
|
||||
auto entry = config.getEntry(key.str());
|
||||
if(entry.type == Configuration::ConfigurationNode::Type::ValueInt && !entry.value.empty()) {
|
||||
if (entry.type == Configuration::ConfigurationNode::Type::ValueInt &&
|
||||
!entry.value.empty()) {
|
||||
uint32_t value = entry.getInteger();
|
||||
if(load->data[pepOffset] != value) {
|
||||
std::cout << "Patching " << key.str() << " = " << std::dec << load->data[pepOffset]
|
||||
if (load->data[pepOffset] != value) {
|
||||
std::cout << "Patching " << key.str() << " = " << std::dec
|
||||
<< load->data[pepOffset]
|
||||
<< " -> " << std::dec << value << " @ " << std::hex << std::setw(6)
|
||||
<< std::setfill('0') << instruction->getAddress() << "\n";
|
||||
}
|
||||
|
@ -323,19 +356,23 @@ void patchImage(const std::string& originalImage, const std::string& settingsFil
|
|||
}
|
||||
|
||||
{
|
||||
for(auto baseOffset : baseOffsets){
|
||||
auto& instruction = imageObject.findInstructionByAddress(baseOffset + 0x9380);
|
||||
if(instruction != nullptr && instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
for (auto baseOffset : baseOffsets) {
|
||||
auto &instruction = imageObject.findInstructionByAddress(baseOffset + 0x9380);
|
||||
if (instruction != nullptr &&
|
||||
instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
auto &load = reinterpret_cast<std::unique_ptr<Instruction::Load> &>(instruction);
|
||||
if (load->address == (uint32_t) getScratchRegister(0x096) && load->data.size() == 9) {
|
||||
for(uint32_t pepOffset = 0; pepOffset < 9; ++pepOffset){
|
||||
for (uint32_t pepOffset = 0; pepOffset < 9; ++pepOffset) {
|
||||
std::stringstream key;
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset << ".ASPMEnable";
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset
|
||||
<< ".ASPMEnable";
|
||||
auto entry = config.getEntry(key.str());
|
||||
if(entry.type == Configuration::ConfigurationNode::Type::ValueBool && !entry.value.empty()) {
|
||||
if (entry.type == Configuration::ConfigurationNode::Type::ValueBool &&
|
||||
!entry.value.empty()) {
|
||||
bool value = entry.getBool();
|
||||
if(load->data[pepOffset] != value) {
|
||||
std::cout << "Patching " << key.str() << " = " << std::dec << load->data[pepOffset]
|
||||
if (load->data[pepOffset] != value) {
|
||||
std::cout << "Patching " << key.str() << " = " << std::dec
|
||||
<< load->data[pepOffset]
|
||||
<< " -> " << std::dec << value << " @ " << std::hex << std::setw(6)
|
||||
<< std::setfill('0') << instruction->getAddress() << "\n";
|
||||
}
|
||||
|
@ -348,20 +385,24 @@ void patchImage(const std::string& originalImage, const std::string& settingsFil
|
|||
}
|
||||
|
||||
{
|
||||
for(uint32_t pepOffset = 0; pepOffset < 9; ++pepOffset){
|
||||
for (uint32_t pepOffset = 0; pepOffset < 9; ++pepOffset) {
|
||||
std::stringstream key;
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset << ".enable";
|
||||
auto entry = config.getEntry(key.str());
|
||||
if(entry.type == Configuration::ConfigurationNode::Type::ValueBool && !entry.value.empty()) {
|
||||
if (entry.type == Configuration::ConfigurationNode::Type::ValueBool && !entry.value.empty()) {
|
||||
bool value = entry.getBool();
|
||||
|
||||
for(auto baseOffset : baseOffsets){
|
||||
auto& instruction = imageObject.findInstructionByAddress(baseOffset + 0x9050 + pepOffset * 0x10);
|
||||
if(instruction != nullptr && instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
for (auto baseOffset : baseOffsets) {
|
||||
auto &instruction = imageObject.findInstructionByAddress(
|
||||
baseOffset + 0x9050 + pepOffset * 0x10);
|
||||
if (instruction != nullptr &&
|
||||
instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
auto &load = reinterpret_cast<std::unique_ptr<Instruction::Load> &>(instruction);
|
||||
if (load->address == (uint32_t) KnownRegisters::MGMT_SCRATCH_0 && load->data.size() == 1) {
|
||||
if(load->data[0] != value) {
|
||||
std::cout << "Patching " << key.str() << " = " << std::dec << load->data[0] << " -> "
|
||||
if (load->address == (uint32_t) KnownRegisters::MGMT_SCRATCH_0 &&
|
||||
load->data.size() == 1) {
|
||||
if (load->data[0] != value) {
|
||||
std::cout << "Patching " << key.str() << " = " << std::dec << load->data[0]
|
||||
<< " -> "
|
||||
<< std::dec << value << " @ " << std::hex << std::setw(6)
|
||||
<< std::setfill('0') << instruction->getAddress() << "\n";
|
||||
}
|
||||
|
@ -374,20 +415,25 @@ void patchImage(const std::string& originalImage, const std::string& settingsFil
|
|||
}
|
||||
|
||||
{
|
||||
for(auto pepOffset : std::vector<uint32_t>{0, 2, 4, 6}){
|
||||
for (auto pepOffset : std::vector<uint32_t>{0, 2, 4, 6}) {
|
||||
std::stringstream key;
|
||||
key << "api.platform.config.switch.0.bootCfg.pep." << std::dec << pepOffset << ".mode";
|
||||
auto entry = config.getEntry(key.str());
|
||||
if(entry.type == Configuration::ConfigurationNode::Type::ValueBool && !entry.value.empty()) {
|
||||
if (entry.type == Configuration::ConfigurationNode::Type::ValueBool && !entry.value.empty()) {
|
||||
bool value = entry.getBool();
|
||||
|
||||
for(auto baseOffset : baseOffsets){
|
||||
auto& instruction = imageObject.findInstructionByAddress(baseOffset + 0x9010 + (pepOffset/2) * 0x10);
|
||||
if(instruction != nullptr && instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
for (auto baseOffset : baseOffsets) {
|
||||
auto &instruction = imageObject.findInstructionByAddress(
|
||||
baseOffset + 0x9010 + (pepOffset / 2) * 0x10);
|
||||
if (instruction != nullptr &&
|
||||
instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
auto &load = reinterpret_cast<std::unique_ptr<Instruction::Load> &>(instruction);
|
||||
if (load->address == (uint32_t) KnownRegisters::MGMT_SCRATCH_0 && load->data.size() == 1) {
|
||||
if(load->data[0] != value){
|
||||
std::cout << "Patching " << key.str() << " = " << std::dec << load->data[0] << " -> " << std::dec << value << " @ " << std::hex << std::setw(6) << std::setfill('0') << instruction->getAddress() << "\n";
|
||||
if (load->address == (uint32_t) KnownRegisters::MGMT_SCRATCH_0 &&
|
||||
load->data.size() == 1) {
|
||||
if (load->data[0] != value) {
|
||||
std::cout << "Patching " << key.str() << " = " << std::dec << load->data[0]
|
||||
<< " -> " << std::dec << value << " @ " << std::hex << std::setw(6)
|
||||
<< std::setfill('0') << instruction->getAddress() << "\n";
|
||||
}
|
||||
load->data[0] = value;
|
||||
}
|
||||
|
@ -399,16 +445,19 @@ void patchImage(const std::string& originalImage, const std::string& settingsFil
|
|||
|
||||
{
|
||||
auto entry = config.getEntry("api.platform.config.switch.0.bootCfg.systimeClockSource");
|
||||
if(entry.type == Configuration::ConfigurationNode::Type::ValueBool && !entry.value.empty()) {
|
||||
if (entry.type == Configuration::ConfigurationNode::Type::ValueBool && !entry.value.empty()) {
|
||||
bool value = entry.getBool();
|
||||
|
||||
for(auto baseOffset : baseOffsets){
|
||||
auto& instruction = imageObject.findInstructionByAddress(baseOffset + 0x9000);
|
||||
if(instruction != nullptr && instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
for (auto baseOffset : baseOffsets) {
|
||||
auto &instruction = imageObject.findInstructionByAddress(baseOffset + 0x9000);
|
||||
if (instruction != nullptr &&
|
||||
instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
auto &load = reinterpret_cast<std::unique_ptr<Instruction::Load> &>(instruction);
|
||||
if (load->address == (uint32_t) KnownRegisters::MGMT_SCRATCH_0 && load->data.size() == 1) {
|
||||
if(load->data[0] != value){
|
||||
std::cout << "Patching bootCfg.systimeClockSource" << " = " << std::dec << load->data[0] << " -> " << std::dec << value << " @ " << std::hex << std::setw(6) << std::setfill('0') << instruction->getAddress() << "\n";
|
||||
if (load->data[0] != value) {
|
||||
std::cout << "Patching bootCfg.systimeClockSource" << " = " << std::dec
|
||||
<< load->data[0] << " -> " << std::dec << value << " @ " << std::hex
|
||||
<< std::setw(6) << std::setfill('0') << instruction->getAddress() << "\n";
|
||||
}
|
||||
load->data[0] = value;
|
||||
}
|
||||
|
@ -419,16 +468,19 @@ void patchImage(const std::string& originalImage, const std::string& settingsFil
|
|||
|
||||
{
|
||||
auto entry = config.getEntry("api.platform.config.switch.0.bootCfg.spiTransferMode");
|
||||
if(entry.type == Configuration::ConfigurationNode::Type::ValueInt && !entry.value.empty()) {
|
||||
if (entry.type == Configuration::ConfigurationNode::Type::ValueInt && !entry.value.empty()) {
|
||||
uint32_t value = entry.getInteger();
|
||||
|
||||
for(auto baseOffset : baseOffsets){
|
||||
auto& instruction = imageObject.findInstructionByAddress(baseOffset + 0x90f0);
|
||||
if(instruction != nullptr && instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
for (auto baseOffset : baseOffsets) {
|
||||
auto &instruction = imageObject.findInstructionByAddress(baseOffset + 0x90f0);
|
||||
if (instruction != nullptr &&
|
||||
instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
auto &load = reinterpret_cast<std::unique_ptr<Instruction::Load> &>(instruction);
|
||||
if (load->address == (uint32_t) KnownRegisters::MGMT_SCRATCH_0 && load->data.size() == 1) {
|
||||
if(load->data[0] != value){
|
||||
std::cout << "Patching bootCfg.spiTransferMode" << " = " << std::dec << load->data[0] << " -> " << std::dec << value << " @ " << std::hex << std::setw(6) << std::setfill('0') << instruction->getAddress() << "\n";
|
||||
if (load->data[0] != value) {
|
||||
std::cout << "Patching bootCfg.spiTransferMode" << " = " << std::dec
|
||||
<< load->data[0] << " -> " << std::dec << value << " @ " << std::hex
|
||||
<< std::setw(6) << std::setfill('0') << instruction->getAddress() << "\n";
|
||||
}
|
||||
load->data[0] = value;
|
||||
}
|
||||
|
@ -439,16 +491,19 @@ void patchImage(const std::string& originalImage, const std::string& settingsFil
|
|||
|
||||
{
|
||||
auto entry = config.getEntry("api.platform.config.switch.0.bootCfg.spiTransferSpeed");
|
||||
if(entry.type == Configuration::ConfigurationNode::Type::ValueInt && !entry.value.empty()) {
|
||||
if (entry.type == Configuration::ConfigurationNode::Type::ValueInt && !entry.value.empty()) {
|
||||
uint32_t value = entry.getInteger();
|
||||
|
||||
for(auto baseOffset : baseOffsets){
|
||||
auto& instruction = imageObject.findInstructionByAddress(baseOffset + 0x9100);
|
||||
if(instruction != nullptr && instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
for (auto baseOffset : baseOffsets) {
|
||||
auto &instruction = imageObject.findInstructionByAddress(baseOffset + 0x9100);
|
||||
if (instruction != nullptr &&
|
||||
instruction->getCommand() == Instruction::Instruction::CommandOp::LOAD) {
|
||||
auto &load = reinterpret_cast<std::unique_ptr<Instruction::Load> &>(instruction);
|
||||
if (load->address == (uint32_t) KnownRegisters::MGMT_SCRATCH_0 && load->data.size() == 1) {
|
||||
if(load->data[0] != value){
|
||||
std::cout << "Patching bootCfg.spiTransferSpeed" << " = " << std::dec << load->data[0] << " -> " << std::dec << value << " @ " << std::hex << std::setw(6) << std::setfill('0') << instruction->getAddress() << "\n";
|
||||
if (load->data[0] != value) {
|
||||
std::cout << "Patching bootCfg.spiTransferSpeed" << " = " << std::dec
|
||||
<< load->data[0] << " -> " << std::dec << value << " @ " << std::hex
|
||||
<< std::setw(6) << std::setfill('0') << instruction->getAddress() << "\n";
|
||||
}
|
||||
load->data[0] = value;
|
||||
}
|
||||
|
@ -461,7 +516,7 @@ void patchImage(const std::string& originalImage, const std::string& settingsFil
|
|||
|
||||
std::ofstream patchedImage(patchedImageFile);
|
||||
|
||||
if(patchedImage.is_open()) {
|
||||
if (patchedImage.is_open()) {
|
||||
auto result = imageObject.toBytes();
|
||||
for (auto c : result) {
|
||||
patchedImage.put(c);
|
||||
|
@ -477,15 +532,15 @@ void patchImage(const std::string& originalImage, const std::string& settingsFil
|
|||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
if(argc >= 2 && strcmp(argv[1], "decode") == 0){
|
||||
if (argc >= 2 && strcmp(argv[1], "decode") == 0) {
|
||||
decodeImage(argv[2]);
|
||||
return 0;
|
||||
}else if(argc >= 4 && strcmp(argv[1], "encode") == 0){
|
||||
} else if (argc >= 4 && strcmp(argv[1], "encode") == 0) {
|
||||
patchImage(argv[2], argv[3], argv[4]);
|
||||
return 0;
|
||||
}else{
|
||||
} else {
|
||||
std::cout << "Usage:\n";
|
||||
std::cout << " decode: " << argv[0] << " decode nvmImage.bin > decoded.txt\n";
|
||||
std::cout << " encode: " << argv[0] << " encode originalNvmImage.bin settings.cfg patchedNvmImage.bin\n";
|
||||
|
|
Loading…
Reference in a new issue