Added image & instruction writeback, Configuration parsing
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
56bccd2168
commit
fbc5c63a47
|
@ -26,4 +26,4 @@ add_executable(rrcSmall
|
|||
|
||||
src/Registers.cpp src/Registers.h
|
||||
src/AnalysisState.cpp src/AnalysisState.h
|
||||
)
|
||||
src/Configuration.cpp src/Configuration.h)
|
28
src/Configuration.cpp
Normal file
28
src/Configuration.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2020, rrcSmall FM10K-Documentation Contributors
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "Configuration.h"
|
226
src/Configuration.h
Normal file
226
src/Configuration.h
Normal file
|
@ -0,0 +1,226 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2020, rrcSmall FM10K-Documentation Contributors
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
|
||||
class Configuration {
|
||||
public:
|
||||
|
||||
Configuration(){
|
||||
|
||||
}
|
||||
|
||||
class ConfigurationNode {
|
||||
public:
|
||||
|
||||
enum class Type {
|
||||
Node = 0,
|
||||
ValueText,
|
||||
ValueInt,
|
||||
ValueBool,
|
||||
} type;
|
||||
|
||||
ConfigurationNode(std::string name, ConfigurationNode::Type type = ConfigurationNode::Type::Node) : name(std::move(name)), type(type){
|
||||
|
||||
}
|
||||
|
||||
std::string name;
|
||||
std::vector<ConfigurationNode> possibleNodes;
|
||||
std::string value;
|
||||
|
||||
std::string getTypeString() const{
|
||||
switch (type) {
|
||||
case Type::Node:
|
||||
return "";
|
||||
case Type::ValueText:
|
||||
return "text";
|
||||
case Type::ValueInt:
|
||||
return "int";
|
||||
case Type::ValueBool:
|
||||
return "bool";
|
||||
}
|
||||
}
|
||||
|
||||
const ConfigurationNode* getSubNode(const std::string& k) const{
|
||||
for (auto& node : possibleNodes){
|
||||
if(node.name == k){
|
||||
return &node;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ConfigurationNode& getOrCreateSubNode(const std::string& k){
|
||||
for (auto& node : possibleNodes){
|
||||
if(node.name == k){
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
possibleNodes.emplace_back(ConfigurationNode(k, ConfigurationNode::Type::Node));
|
||||
return possibleNodes[possibleNodes.size() - 1];
|
||||
}
|
||||
|
||||
bool getBool() const{
|
||||
return value == "true";
|
||||
}
|
||||
|
||||
int getInteger() const{
|
||||
return std::stoi(value, nullptr, 0);
|
||||
}
|
||||
|
||||
const std::string& getText() const{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
ConfigurationNode mainNode = ConfigurationNode("");
|
||||
|
||||
std::vector<std::string> getAllEntries() const{
|
||||
std::vector<std::string> entries;
|
||||
|
||||
for(const auto& n : mainNode.possibleNodes){
|
||||
if(n.type == ConfigurationNode::Type::Node){
|
||||
getAllEntriesForNode(entries, n, n.name + ".");
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(entries.begin(), entries.end());
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
void getAllEntriesForNode(std::vector<std::string>& entries, const 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{
|
||||
getAllEntriesForNode(entries, n, key + n.name + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ConfigurationNode& getEntry(const std::string& entry) const{
|
||||
if(entry.empty() || entry[0] == '#'){
|
||||
return mainNode;
|
||||
}
|
||||
std::string currentKey;
|
||||
currentKey.reserve(16);
|
||||
|
||||
const ConfigurationNode* currentNode = &mainNode;
|
||||
|
||||
for(char c : entry){
|
||||
if((c == '.' || c == ' ' || c == '\t')){
|
||||
if(!currentKey.empty()){
|
||||
currentNode = currentNode->getSubNode(currentKey);
|
||||
|
||||
if(currentNode == nullptr){
|
||||
return mainNode;
|
||||
}
|
||||
|
||||
currentKey.clear();
|
||||
|
||||
if(c == ' ' || c == '\t'){
|
||||
return *currentNode;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
currentKey += c;
|
||||
}
|
||||
}
|
||||
|
||||
return mainNode;
|
||||
}
|
||||
|
||||
bool addEntry(const std::string& entry){
|
||||
if(entry.empty() || entry[0] == '#'){
|
||||
return false;
|
||||
}
|
||||
std::string currentKey;
|
||||
currentKey.reserve(16);
|
||||
|
||||
uint32_t state = 0;
|
||||
|
||||
ConfigurationNode* currentNode = &mainNode;
|
||||
|
||||
for(size_t i = 0; i < entry.size(); ++i){
|
||||
auto c = entry[i];
|
||||
if(state == 0){
|
||||
if((c == '.' || c == ' ' || c == '\t')){
|
||||
if(!currentKey.empty()){
|
||||
currentNode = ¤tNode->getOrCreateSubNode(currentKey);
|
||||
|
||||
currentKey.clear();
|
||||
|
||||
if(c == ' ' || c == '\t'){
|
||||
state = 1;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
currentKey += c;
|
||||
}
|
||||
} else if(state == 1){
|
||||
if((c == ' ' || c == '\t')){
|
||||
if(!currentKey.empty()){
|
||||
if(currentKey == "int"){
|
||||
currentNode->type = ConfigurationNode::Type::ValueInt;
|
||||
}else if(currentKey == "text"){
|
||||
currentNode->type = ConfigurationNode::Type::ValueText;
|
||||
}else if(currentKey == "bool"){
|
||||
currentNode->type = ConfigurationNode::Type::ValueBool;
|
||||
}
|
||||
|
||||
currentKey.clear();
|
||||
|
||||
state = 2;
|
||||
}
|
||||
}else{
|
||||
currentKey += c;
|
||||
}
|
||||
} else if(state == 2){
|
||||
if(i == (entry.size() - 1)){
|
||||
currentKey += c;
|
||||
currentNode->value = currentKey;
|
||||
}else if((c == ' ' || c == '\t') && currentKey.empty()){
|
||||
|
||||
} else {
|
||||
currentKey += c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return state == 2;
|
||||
}
|
||||
|
||||
};
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
const std::unique_ptr<Instruction::Instruction> ImageFormat::NULL_INSTRUCTION(nullptr);
|
||||
|
||||
ImageFormat ImageFormat::fromBytes(const std::vector<uint8_t>& imageBytes, bool prefetchInitialZone) {
|
||||
ImageFormat ImageFormat::fromBytes(const std::vector<uint8_t>& imageBytes) {
|
||||
ImageFormat image;
|
||||
|
||||
image.baseImage = imageBytes;
|
||||
|
@ -55,6 +55,13 @@ ImageFormat ImageFormat::fromBytes(const std::vector<uint8_t>& imageBytes, bool
|
|||
|
||||
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){
|
||||
image.imageSignature += currentCharacter;
|
||||
}
|
||||
|
||||
std::cout << "SIGNATURE: " << image.imageSignature << "\n";
|
||||
|
||||
offset = CFG_HEADER;
|
||||
image.cfgHeader.length = imageBytes[offset++];
|
||||
|
@ -85,46 +92,96 @@ ImageFormat ImageFormat::fromBytes(const std::vector<uint8_t>& imageBytes, bool
|
|||
do{
|
||||
character = imageBytes[offset++];
|
||||
++bytesCnt;
|
||||
if(character != '\n' && character != 0xFF){
|
||||
if(character != 0xFF){
|
||||
currentEntry += character;
|
||||
if(character == '\n'){
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
|
||||
if(!currentEntry.empty()){
|
||||
image.bootConfig.push_back(currentEntry);
|
||||
if(currentEntry[currentEntry.size() - 1] == '\n'){
|
||||
currentEntry.resize(currentEntry.size() - 1);
|
||||
}
|
||||
image.bootConfig.addEntry(currentEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint32_t> branches;
|
||||
|
||||
/*if(prefetchInitialZone){
|
||||
offset = image.header.baseAddress;
|
||||
|
||||
Instruction::CommandOp lastOp;
|
||||
do{
|
||||
auto instruction = Instruction::fromBytes(offset, image.baseImage);
|
||||
offset = instruction.endAddress;
|
||||
lastOp = instruction.getCommand();
|
||||
|
||||
if(instruction.getCommand() != Instruction::CommandOp::NOP){
|
||||
auto nextBranches = instruction.getPossibleBranches();
|
||||
branches.insert(branches.end(), nextBranches.begin(), nextBranches.end());
|
||||
image.instructions.push_back(std::move(instruction));
|
||||
}
|
||||
} while (lastOp != Instruction::CommandOp::END && lastOp != Instruction::CommandOp::NOP);
|
||||
}else{*/
|
||||
branches.push_back(image.header.baseAddress);
|
||||
//}
|
||||
|
||||
image.decodeAnalyzeInstructionsAt(image.header.baseAddress);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> ImageFormat::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
bytes.resize(baseImage.size(), 0xFF);
|
||||
|
||||
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){
|
||||
bytes[offset] = baseImage[offset];
|
||||
}
|
||||
|
||||
bytes[offset++] = cfgHeader.length;
|
||||
bytes[offset++] = (cfgHeader.base >> 16) & 0xFF;
|
||||
bytes[offset++] = (cfgHeader.base >> 8) & 0xFF;
|
||||
bytes[offset++] = cfgHeader.base & 0xFF;
|
||||
|
||||
for(; offset < CFG_SIGNATURE; ++offset){
|
||||
bytes[offset] = baseImage[offset];
|
||||
}
|
||||
|
||||
std::copy(imageSignature.begin(), imageSignature.end(), bytes.begin() + offset);
|
||||
|
||||
offset += imageSignature.length();
|
||||
|
||||
for(; offset < cfgHeader.base; ++offset){
|
||||
bytes[offset] = baseImage[offset];
|
||||
}
|
||||
|
||||
bytes[offset++] = cfg.fileFormat;
|
||||
bytes[offset++] = cfg.version;
|
||||
|
||||
bytes[offset++] = ((cfg.length >> 4) >> 8) & 0xFF;
|
||||
bytes[offset++] = (cfg.length >> 4) & 0xFF;
|
||||
|
||||
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()) {
|
||||
std::copy(entry.begin(), entry.end(), bytes.begin() + offset);
|
||||
offset += entry.length();
|
||||
bytes[offset++] = '\n';
|
||||
}
|
||||
bytes[offset++] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
std::copy(baseImage.begin() + offset, baseImage.end(), bytes.begin() + offset);
|
||||
|
||||
for (const auto& entry : instructions){
|
||||
auto data = entry.second->toBytes();
|
||||
std::copy(data.begin(), data.end(), bytes.begin() + entry.second->getAddress());
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
|
||||
|
@ -168,7 +225,7 @@ void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
|
|||
|
||||
state.current &= 0xfffffffc;
|
||||
|
||||
if(instruction == nullptr || instruction->getCommand() == Instruction::Instruction::CommandOp::NOP){
|
||||
if(instruction == nullptr){
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -244,4 +301,4 @@ 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <map>
|
||||
|
||||
#include "SmallFirmwareFormat.h"
|
||||
#include "Configuration.h"
|
||||
#include "instructions/Instruction.h"
|
||||
|
||||
class ImageFormat{
|
||||
|
@ -58,7 +59,7 @@ public:
|
|||
};
|
||||
|
||||
|
||||
static ImageFormat fromBytes(const std::vector<uint8_t>& image, bool prefetchInitialZone = false);
|
||||
static ImageFormat fromBytes(const std::vector<uint8_t>& image);
|
||||
|
||||
void decodeAnalyzeInstructionsAt(uint32_t offset);
|
||||
|
||||
|
@ -105,6 +106,8 @@ public:
|
|||
return bootConfig;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> toBytes() const;
|
||||
|
||||
private:
|
||||
|
||||
struct {
|
||||
|
@ -114,7 +117,8 @@ private:
|
|||
uint32_t baseAddress : 24;
|
||||
} header;
|
||||
|
||||
static const int CFG_HEADER = 0x4 << 2;
|
||||
static const int CFG_SIGNATURE = 0x100;
|
||||
static const int CFG_HEADER = 16;
|
||||
static const int CFG_LENGTH = 16;
|
||||
|
||||
static const std::unique_ptr<Instruction::Instruction> NULL_INSTRUCTION;
|
||||
|
@ -130,9 +134,11 @@ private:
|
|||
uint16_t length : 16;
|
||||
} cfg;
|
||||
|
||||
std::vector<std::string> bootConfig;
|
||||
Configuration bootConfig;
|
||||
|
||||
std::map<uint32_t, std::unique_ptr<Instruction::Instruction>> instructions;
|
||||
|
||||
std::vector<uint8_t> baseImage;
|
||||
|
||||
std::string imageSignature;
|
||||
};
|
|
@ -58,9 +58,7 @@ void Instruction::Branch::fromBytes(uint32_t offset, const std::vector<uint8_t>
|
|||
jumpAddress |= bytes[offset++] << 8;
|
||||
jumpAddress |= bytes[offset++];
|
||||
|
||||
while ((offset % 4) != 0){
|
||||
offset++;
|
||||
}
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
@ -103,3 +101,31 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
|
||||
return branches;
|
||||
}
|
||||
|
||||
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((address >> 16) & 0xFF);
|
||||
bytes.emplace_back((address >> 8) & 0xFF);
|
||||
bytes.emplace_back(address & 0xFF);
|
||||
|
||||
bytes.emplace_back((value >> 24) & 0xFF);
|
||||
bytes.emplace_back((value >> 16) & 0xFF);
|
||||
bytes.emplace_back((value >> 8) & 0xFF);
|
||||
bytes.emplace_back(value & 0xFF);
|
||||
|
||||
bytes.emplace_back((mask >> 24) & 0xFF);
|
||||
bytes.emplace_back((mask >> 16) & 0xFF);
|
||||
bytes.emplace_back((mask >> 8) & 0xFF);
|
||||
bytes.emplace_back(mask & 0xFF);
|
||||
|
||||
bytes.emplace_back(0x00);
|
||||
|
||||
bytes.emplace_back((jumpAddress >> 16) & 0xFF);
|
||||
bytes.emplace_back((jumpAddress >> 8) & 0xFF);
|
||||
bytes.emplace_back(jumpAddress & 0xFF);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ namespace Instruction{
|
|||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
std::string toString() const override;
|
||||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
@ -50,7 +52,7 @@ namespace Instruction{
|
|||
|
||||
|
||||
uint8_t addressOffset;
|
||||
bool equality;
|
||||
uint8_t equality;
|
||||
uint32_t address;
|
||||
uint32_t value;
|
||||
uint32_t mask;
|
||||
|
|
|
@ -54,9 +54,7 @@ void Instruction::Calc::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
addressTarget |= bytes[offset++] << 8;
|
||||
addressTarget |= bytes[offset++];
|
||||
|
||||
while ((offset % 4) != 0){
|
||||
offset++;
|
||||
}
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
@ -135,3 +133,27 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
}
|
||||
|
||||
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((addressDestination >> 16) & 0xFF);
|
||||
bytes.emplace_back((addressDestination >> 8) & 0xFF);
|
||||
bytes.emplace_back(addressDestination & 0xFF);
|
||||
|
||||
bytes.emplace_back(0x00);
|
||||
|
||||
bytes.emplace_back((addressSource >> 16) & 0xFF);
|
||||
bytes.emplace_back((addressSource >> 8) & 0xFF);
|
||||
bytes.emplace_back(addressSource & 0xFF);
|
||||
|
||||
bytes.emplace_back(0x00);
|
||||
|
||||
bytes.emplace_back((addressTarget >> 16) & 0xFF);
|
||||
bytes.emplace_back((addressTarget >> 8) & 0xFF);
|
||||
bytes.emplace_back(addressTarget & 0xFF);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,8 @@ namespace Instruction{
|
|||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
std::string toString() const override;
|
||||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
|
|
@ -54,9 +54,7 @@ void Instruction::CalcImm::fromBytes(uint32_t offset, const std::vector<uint8_t>
|
|||
value |= bytes[offset++] << 8;
|
||||
value |= bytes[offset++];
|
||||
|
||||
while ((offset % 4) != 0){
|
||||
offset++;
|
||||
}
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
@ -134,3 +132,26 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
}
|
||||
|
||||
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((addressDestination >> 16) & 0xFF);
|
||||
bytes.emplace_back((addressDestination >> 8) & 0xFF);
|
||||
bytes.emplace_back(addressDestination & 0xFF);
|
||||
|
||||
bytes.emplace_back(0x00);
|
||||
|
||||
bytes.emplace_back((addressSource >> 16) & 0xFF);
|
||||
bytes.emplace_back((addressSource >> 8) & 0xFF);
|
||||
bytes.emplace_back(addressSource & 0xFF);
|
||||
|
||||
bytes.emplace_back((value >> 24) & 0xFF);
|
||||
bytes.emplace_back((value >> 16) & 0xFF);
|
||||
bytes.emplace_back((value >> 8) & 0xFF);
|
||||
bytes.emplace_back(value & 0xFF);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ namespace Instruction{
|
|||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
std::string toString() const override;
|
||||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
|
|
@ -49,9 +49,7 @@ void Instruction::Copy::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
addressBB |= bytes[offset++] << 8;
|
||||
addressBB |= bytes[offset++];
|
||||
|
||||
while ((offset % 4) != 0){
|
||||
offset++;
|
||||
}
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
@ -79,3 +77,22 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
}
|
||||
|
||||
|
||||
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((addressAA >> 16) & 0xFF);
|
||||
bytes.emplace_back((addressAA >> 8) & 0xFF);
|
||||
bytes.emplace_back(addressAA & 0xFF);
|
||||
|
||||
bytes.emplace_back(0);
|
||||
|
||||
bytes.emplace_back((addressBB >> 16) & 0xFF);
|
||||
bytes.emplace_back((addressBB >> 8) & 0xFF);
|
||||
bytes.emplace_back(addressBB & 0xFF);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ namespace Instruction{
|
|||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
std::string toString() const override;
|
||||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
|
|
@ -30,11 +30,7 @@
|
|||
void Instruction::End::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
|
||||
_address = offset;
|
||||
|
||||
offset++;
|
||||
|
||||
while ((offset % 4) != 0){
|
||||
offset++;
|
||||
}
|
||||
offset += 4;
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
@ -52,3 +48,15 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Instruction::End::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand());
|
||||
|
||||
bytes.emplace_back(0xFF);
|
||||
bytes.emplace_back(0xFF);
|
||||
bytes.emplace_back(0xFF);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ namespace Instruction{
|
|||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
std::string toString() const override;
|
||||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
|
|
@ -58,9 +58,7 @@ void Instruction::Init::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
data_add |= bytes[offset++] << 8;
|
||||
data_add |= bytes[offset++];
|
||||
|
||||
while ((offset % 4) != 0){
|
||||
offset++;
|
||||
}
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
@ -93,3 +91,31 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
}
|
||||
|
||||
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((address >> 16) & 0xFF);
|
||||
bytes.emplace_back((address >> 8) & 0xFF);
|
||||
bytes.emplace_back(address & 0xFF);
|
||||
|
||||
bytes.emplace_back(0x00);
|
||||
|
||||
bytes.emplace_back((count >> 16) & 0xFF);
|
||||
bytes.emplace_back((count >> 8) & 0xFF);
|
||||
bytes.emplace_back(count & 0xFF);
|
||||
|
||||
bytes.emplace_back((data >> 24) & 0xFF);
|
||||
bytes.emplace_back((data >> 16) & 0xFF);
|
||||
bytes.emplace_back((data >> 8) & 0xFF);
|
||||
bytes.emplace_back(data & 0xFF);
|
||||
|
||||
bytes.emplace_back((data_add >> 24) & 0xFF);
|
||||
bytes.emplace_back((data_add >> 16) & 0xFF);
|
||||
bytes.emplace_back((data_add >> 8) & 0xFF);
|
||||
bytes.emplace_back(data_add & 0xFF);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ namespace Instruction{
|
|||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
std::string toString() const override;
|
||||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
@ -50,7 +52,7 @@ namespace Instruction{
|
|||
|
||||
|
||||
uint8_t addressOffset;
|
||||
bool increment;
|
||||
uint8_t increment;
|
||||
uint32_t address;
|
||||
uint32_t count;
|
||||
uint32_t data;
|
||||
|
|
|
@ -91,8 +91,6 @@ namespace Instruction{
|
|||
case CommandOp::END:
|
||||
result = std::make_unique<End>();
|
||||
break;
|
||||
case CommandOp::NOP:
|
||||
break;
|
||||
}
|
||||
|
||||
if(result != nullptr){
|
||||
|
@ -133,7 +131,7 @@ namespace Instruction{
|
|||
return CommandOp::END;
|
||||
}
|
||||
|
||||
return CommandOp::NOP;
|
||||
return CommandOp::END;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,20 +55,20 @@ namespace Instruction{
|
|||
*/
|
||||
|
||||
enum class CommandOp : uint8_t {
|
||||
WRITE = 0,
|
||||
COPY,
|
||||
LOAD,
|
||||
INIT,
|
||||
CALC,
|
||||
CALC_IMM,
|
||||
BRANCH,
|
||||
POLL,
|
||||
LOOP,
|
||||
JUMP,
|
||||
RETURN,
|
||||
SET,
|
||||
WAIT,
|
||||
END,
|
||||
WRITE = 0b00000000,
|
||||
COPY = 0b01000000,
|
||||
LOAD = 0b11000000,
|
||||
INIT = 0b11001000,
|
||||
CALC = 0b10000000,
|
||||
CALC_IMM = 0b10100000,
|
||||
BRANCH = 0b11010000,
|
||||
POLL = 0b11011000,
|
||||
LOOP = 0b11100000,
|
||||
JUMP = 0b11101000,
|
||||
RETURN = 0b11110000,
|
||||
SET = 0b11111000,
|
||||
WAIT = 0xFE,
|
||||
END = 0xFF,
|
||||
NOP = 0xFF
|
||||
};
|
||||
|
||||
|
@ -83,6 +83,8 @@ namespace Instruction{
|
|||
|
||||
virtual void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) = 0;
|
||||
|
||||
virtual std::vector<uint8_t> toBytes() const = 0;
|
||||
|
||||
virtual std::string toString() const = 0;
|
||||
|
||||
virtual std::vector<uint32_t> getPossibleBranches() const = 0;
|
||||
|
|
|
@ -39,9 +39,7 @@ void Instruction::Jump::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
jumpAddress |= bytes[offset++] << 8;
|
||||
jumpAddress |= bytes[offset++];
|
||||
|
||||
while ((offset % 4) != 0){
|
||||
offset++;
|
||||
}
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
@ -62,3 +60,16 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Instruction::Jump::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand());
|
||||
|
||||
bytes.emplace_back((jumpAddress >> 16) & 0xFF);
|
||||
bytes.emplace_back((jumpAddress >> 8) & 0xFF);
|
||||
bytes.emplace_back(jumpAddress & 0xFF);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ namespace Instruction{
|
|||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
std::string toString() const override;
|
||||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
|
|
@ -58,9 +58,7 @@ void Instruction::Load::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
}
|
||||
|
||||
|
||||
while ((offset % 4) != 0){
|
||||
offset++;
|
||||
}
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
@ -132,3 +130,28 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
}
|
||||
|
||||
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((address >> 16) & 0xFF);
|
||||
bytes.emplace_back((address >> 8) & 0xFF);
|
||||
bytes.emplace_back(address & 0xFF);
|
||||
|
||||
bytes.emplace_back(0x00);
|
||||
|
||||
bytes.emplace_back((data.size() >> 16) & 0xFF);
|
||||
bytes.emplace_back((data.size() >> 8) & 0xFF);
|
||||
bytes.emplace_back(data.size() & 0xFF);
|
||||
|
||||
for (auto d : data) {
|
||||
bytes.emplace_back((d >> 24) & 0xFF);
|
||||
bytes.emplace_back((d >> 16) & 0xFF);
|
||||
bytes.emplace_back((d >> 8) & 0xFF);
|
||||
bytes.emplace_back(d & 0xFF);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ namespace Instruction{
|
|||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
std::string toString() const override;
|
||||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
@ -50,7 +52,7 @@ namespace Instruction{
|
|||
|
||||
|
||||
uint8_t addressOffset;
|
||||
bool increment;
|
||||
uint8_t increment;
|
||||
uint32_t address;
|
||||
std::vector<uint32_t> data;
|
||||
};
|
||||
|
|
|
@ -41,9 +41,7 @@ void Instruction::Loop::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
jumpAddress |= bytes[offset++] << 8;
|
||||
jumpAddress |= bytes[offset++];
|
||||
|
||||
while ((offset % 4) != 0){
|
||||
offset++;
|
||||
}
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
@ -80,3 +78,15 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
|
||||
return branches;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Instruction::Loop::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand() | counter);
|
||||
|
||||
bytes.emplace_back((jumpAddress >> 16) & 0xFF);
|
||||
bytes.emplace_back((jumpAddress >> 8) & 0xFF);
|
||||
bytes.emplace_back(jumpAddress & 0xFF);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ namespace Instruction{
|
|||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
std::string toString() const override;
|
||||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
|
|
@ -64,9 +64,7 @@ void Instruction::Poll::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
jumpAddress |= bytes[offset++] << 8;
|
||||
jumpAddress |= bytes[offset++];
|
||||
|
||||
while ((offset % 4) != 0){
|
||||
offset++;
|
||||
}
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
@ -109,3 +107,39 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
|
||||
return branches;
|
||||
}
|
||||
|
||||
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((address >> 16) & 0xFF);
|
||||
bytes.emplace_back((address >> 8) & 0xFF);
|
||||
bytes.emplace_back(address & 0xFF);
|
||||
|
||||
bytes.emplace_back((value >> 24) & 0xFF);
|
||||
bytes.emplace_back((value >> 16) & 0xFF);
|
||||
bytes.emplace_back((value >> 8) & 0xFF);
|
||||
bytes.emplace_back(value & 0xFF);
|
||||
|
||||
bytes.emplace_back((mask >> 24) & 0xFF);
|
||||
bytes.emplace_back((mask >> 16) & 0xFF);
|
||||
bytes.emplace_back((mask >> 8) & 0xFF);
|
||||
bytes.emplace_back(mask & 0xFF);
|
||||
|
||||
|
||||
bytes.emplace_back((maxRetry >> 8) & 0xFF);
|
||||
bytes.emplace_back(maxRetry & 0xFF);
|
||||
|
||||
|
||||
bytes.emplace_back((retryInterval >> 8) & 0xFF);
|
||||
bytes.emplace_back(retryInterval & 0xFF);
|
||||
|
||||
bytes.emplace_back(0x00);
|
||||
|
||||
bytes.emplace_back((jumpAddress >> 16) & 0xFF);
|
||||
bytes.emplace_back((jumpAddress >> 8) & 0xFF);
|
||||
bytes.emplace_back(jumpAddress & 0xFF);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ namespace Instruction{
|
|||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
std::string toString() const override;
|
||||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
@ -50,7 +52,7 @@ namespace Instruction{
|
|||
|
||||
|
||||
uint8_t addressOffset;
|
||||
bool equality;
|
||||
uint8_t equality;
|
||||
uint32_t address;
|
||||
uint32_t value;
|
||||
uint32_t mask;
|
||||
|
|
|
@ -41,9 +41,7 @@ void Instruction::Return::fromBytes(uint32_t offset, const std::vector<uint8_t>
|
|||
address |= bytes[offset++] << 8;
|
||||
address |= bytes[offset++];
|
||||
|
||||
while ((offset % 4) != 0){
|
||||
offset++;
|
||||
}
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
@ -67,3 +65,16 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
}
|
||||
|
||||
|
||||
std::vector<uint8_t> Instruction::Return::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand() | addressOffset);
|
||||
|
||||
bytes.emplace_back((address >> 16) & 0xFF);
|
||||
bytes.emplace_back((address >> 8) & 0xFF);
|
||||
bytes.emplace_back(address & 0xFF);
|
||||
|
||||
return bytes;
|
||||
}
|
|
@ -42,6 +42,8 @@ namespace Instruction{
|
|||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
std::string toString() const override;
|
||||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
|
|
@ -51,9 +51,7 @@ void Instruction::Set::fromBytes(uint32_t offset, const std::vector<uint8_t> &by
|
|||
mask |= bytes[offset++] << 8;
|
||||
mask |= bytes[offset++];
|
||||
|
||||
while ((offset % 4) != 0){
|
||||
offset++;
|
||||
}
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
@ -77,3 +75,25 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Instruction::Set::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand() | addressOffset);
|
||||
|
||||
bytes.emplace_back((address >> 16) & 0xFF);
|
||||
bytes.emplace_back((address >> 8) & 0xFF);
|
||||
bytes.emplace_back(address & 0xFF);
|
||||
|
||||
bytes.emplace_back((value >> 24) & 0xFF);
|
||||
bytes.emplace_back((value >> 16) & 0xFF);
|
||||
bytes.emplace_back((value >> 8) & 0xFF);
|
||||
bytes.emplace_back(value & 0xFF);
|
||||
|
||||
bytes.emplace_back((mask >> 24) & 0xFF);
|
||||
bytes.emplace_back((mask >> 16) & 0xFF);
|
||||
bytes.emplace_back((mask >> 8) & 0xFF);
|
||||
bytes.emplace_back(mask & 0xFF);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ namespace Instruction{
|
|||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
std::string toString() const override;
|
||||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
|
|
@ -39,9 +39,7 @@ void Instruction::Wait::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
|
|||
time |= bytes[offset++] << 8;
|
||||
time |= bytes[offset++];
|
||||
|
||||
while ((offset % 4) != 0){
|
||||
offset++;
|
||||
}
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
@ -64,3 +62,16 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Instruction::Wait::toBytes() const {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
bytes.emplace_back((uint8_t)getCommand());
|
||||
|
||||
bytes.emplace_back((time >> 16) & 0xFF);
|
||||
bytes.emplace_back((time >> 8) & 0xFF);
|
||||
bytes.emplace_back(time & 0xFF);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ namespace Instruction{
|
|||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
std::string toString() const override;
|
||||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
|
|
@ -51,9 +51,7 @@ void Instruction::Write::fromBytes(uint32_t offset, const std::vector<uint8_t> &
|
|||
}
|
||||
|
||||
|
||||
while ((offset % 4) != 0){
|
||||
offset++;
|
||||
}
|
||||
|
||||
|
||||
_endAddress = offset;
|
||||
}
|
||||
|
@ -83,3 +81,22 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> Instruc
|
|||
|
||||
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
|
||||
}
|
||||
|
||||
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((address >> 16) & 0xFF);
|
||||
bytes.emplace_back((address >> 8) & 0xFF);
|
||||
bytes.emplace_back(address & 0xFF);
|
||||
|
||||
for (auto d : data) {
|
||||
bytes.emplace_back((d >> 24) & 0xFF);
|
||||
bytes.emplace_back((d >> 16) & 0xFF);
|
||||
bytes.emplace_back((d >> 8) & 0xFF);
|
||||
bytes.emplace_back(d & 0xFF);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
@ -27,11 +27,17 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "Instruction.h"
|
||||
|
||||
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(){
|
||||
|
||||
}
|
||||
|
@ -42,6 +48,8 @@ namespace Instruction{
|
|||
|
||||
void fromBytes(uint32_t offset, const std::vector<uint8_t>& bytes) override;
|
||||
|
||||
std::vector<uint8_t> toBytes() const override;
|
||||
|
||||
std::string toString() const override;
|
||||
|
||||
std::vector<uint32_t> getPossibleBranches() const override;
|
||||
|
|
61
src/main.cpp
61
src/main.cpp
|
@ -29,33 +29,21 @@
|
|||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <cstring>
|
||||
|
||||
#include "ImageFormat.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if(argc < 2){
|
||||
std::cout << "Usage: " << argv[0] << " nvmImage.bin > decoded.txt\n";
|
||||
return 1;
|
||||
}
|
||||
void decodeImage(const std::string& fileName){
|
||||
|
||||
/*
|
||||
std::vector<uint8_t> v{0x00, 0x04, 0x01, 0x04, 0x00, 0x00, 0x00, 0x19};
|
||||
for (uint8_t &c: v)
|
||||
std::cout << std::hex << (uint32_t) c << "\n";
|
||||
auto instruction = ImageFormat::Instruction::fromBytes(0, v);
|
||||
std::cout << instruction.toString();
|
||||
return 0;
|
||||
*/
|
||||
|
||||
std::ifstream image(argv[1]);
|
||||
std::ifstream image(fileName);
|
||||
if(image.is_open()){
|
||||
std::vector<uint8_t> bytes;
|
||||
while(!image.eof()){
|
||||
bytes.push_back(image.get());
|
||||
}
|
||||
auto imageObject = ImageFormat::fromBytes(bytes, false);
|
||||
auto imageObject = ImageFormat::fromBytes(bytes);
|
||||
|
||||
for(auto& k : imageObject.getBootConfig()){
|
||||
for(auto& k : imageObject.getBootConfig().getAllEntries()){
|
||||
std::cout << k << "\n";
|
||||
}
|
||||
|
||||
|
@ -89,6 +77,41 @@ int main(int argc, char* argv[]) {
|
|||
prevAddress = instruction->getEndAddress();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void patchImage(const std::string& originalImage, const std::string& settings, const std::string& patchedImageFile){
|
||||
std::ifstream image(originalImage);
|
||||
if(image.is_open()) {
|
||||
std::vector<uint8_t> bytes;
|
||||
while (!image.eof()) {
|
||||
bytes.push_back(image.get());
|
||||
}
|
||||
auto imageObject = ImageFormat::fromBytes(bytes);
|
||||
|
||||
//Do patch
|
||||
|
||||
std::ofstream patchedImage(patchedImageFile);
|
||||
auto result = imageObject.toBytes();
|
||||
for (auto c : result) {
|
||||
patchedImage.put(c);
|
||||
}
|
||||
patchedImage.close();
|
||||
image.close();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
if(argc >= 2 && strcmp(argv[1], "decode") == 0){
|
||||
decodeImage(argv[2]);
|
||||
return 0;
|
||||
}else if(argc >= 4 && strcmp(argv[1], "encode") == 0){
|
||||
patchImage(argv[2], argv[3], argv[4]);
|
||||
return 0;
|
||||
}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";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue