Merge pull request 'Annotated assembly output' (#2) from tagged-asm into master
All checks were successful
continuous-integration/drone/push Build is passing

Reviewed-on: #2
This commit is contained in:
DataHoarder 2020-12-29 12:18:04 +00:00
commit fd36be8599
Signed by: GammaSpectra.live Git
GPG key ID: 8B02E6093E9CB7B3
40 changed files with 1189 additions and 141 deletions

View file

@ -7,6 +7,7 @@ set(SOURCE_FILES
src/ImageFormat.cpp src/ImageFormat.h
src/SmallFirmwareFormat.cpp src/SmallFirmwareFormat.h
src/instructions/AddressOffset.h
src/instructions/Instruction.cpp src/instructions/Instruction.h
src/instructions/Write.cpp src/instructions/Write.h
src/instructions/Copy.cpp src/instructions/Copy.h
@ -26,7 +27,8 @@ set(SOURCE_FILES
src/Registers.cpp src/Registers.h
src/AnalysisState.cpp src/AnalysisState.h
src/Configuration.cpp src/Configuration.h
)
src/OutputContext.cpp src/OutputContext.h
)
add_library(rrcimage STATIC ${SOURCE_FILES})

View file

@ -34,4 +34,16 @@ uint32_t AnalysisState::getAddressOffset(uint8_t offsetEntry) const {
return 0;
}
return getRegister((uint32_t) KnownRegisters::BSM_ADDR_OFFSET_0 + offsetEntry);
}
}
uint32_t AnalysisState::getRegister(const Instruction::AddressWithOffset &address) const {
return getRegister(getAddressWithOffset(address));
}
void AnalysisState::setRegister(const Instruction::AddressWithOffset &address, uint32_t value) {
setRegister(getAddressWithOffset(address), value);
}
uint32_t AnalysisState::getAddressWithOffset(const Instruction::AddressWithOffset &address) const {
return address.address + getAddressOffset(address.offset);
}

View file

@ -30,10 +30,24 @@
#include <cstdint>
#include <unordered_map>
#include <algorithm>
#include "SmallFirmwareFormat.h"
#include "instructions/AddressOffset.h"
enum class JumpKind {
Continue,
Absolute,
Speculative,
Branch,
Loop,
Return
};
typedef std::unordered_map<uint32_t, std::vector<std::pair<uint32_t, JumpKind>>> AnalysisJumpTable;
class AnalysisState {
public:
std::unordered_map<uint32_t, uint32_t> memory;
uint32_t previous;
uint32_t current;
@ -41,13 +55,26 @@ public:
SmallFirmwareFormat pciSPICOFirmware;
SmallFirmwareFormat pciSerDesFirmware;
AnalysisState(uint32_t initial) : current(initial), previous(0) {
AnalysisJumpTable &jumpTable;
void addKnownJump(uint32_t to, uint32_t from, JumpKind kind) {
if (jumpTable.find(to) == jumpTable.end()) {
jumpTable[to] = std::vector<std::pair<uint32_t, JumpKind>>{{from, kind}};
} else if (std::find(jumpTable[to].begin(), jumpTable[to].end(), std::pair<uint32_t, JumpKind>(from, kind)) ==
jumpTable[to].end()) {
jumpTable[to].emplace_back(from, kind);
}
}
AnalysisState(uint32_t initial, AnalysisJumpTable &table) : current(initial), previous(0), jumpTable(table) {
}
AnalysisState(const AnalysisState &oldState) : current(oldState.current), previous(oldState.previous),
memory(oldState.memory), pciSPICOFirmware(oldState.pciSPICOFirmware),
pciSerDesFirmware(oldState.pciSerDesFirmware) {
pciSerDesFirmware(oldState.pciSerDesFirmware),
jumpTable(oldState.jumpTable) {
}
@ -55,13 +82,19 @@ public:
return current == other.current && memory == other.memory;
}
void setRegister(const Instruction::AddressWithOffset &address, uint32_t value);
void setRegister(uint32_t addr, uint32_t value) {
memory[addr] = value;
}
uint32_t getRegister(const Instruction::AddressWithOffset &address) const;
uint32_t getRegister(uint32_t addr) const {
return memory.find(addr) == memory.end() ? 0 : memory.at(addr);
}
uint32_t getAddressWithOffset(const Instruction::AddressWithOffset &address) const;
uint32_t getAddressOffset(uint8_t offsetEntry) const;
};

View file

@ -112,7 +112,7 @@ ImageFormat ImageFormat::fromBytes(const std::vector<uint8_t> &imageBytes) {
std::vector<uint8_t> ImageFormat::toBytes() const {
std::vector<uint8_t> bytes;
bytes.resize(baseImage.size() - 1, 0xFF);
bytes.resize(getBaseImage().size() - 1, 0xFF);
uint32_t offset = 0;
@ -123,7 +123,7 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
bytes[offset++] = header.baseAddress & 0xFF;
for (; offset < CFG_HEADER; ++offset) {
bytes[offset] = baseImage[offset];
bytes[offset] = getBaseImage()[offset];
}
bytes[offset++] = cfgHeader.length;
@ -132,7 +132,7 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
bytes[offset++] = cfgHeader.base & 0xFF;
for (; offset < CFG_SIGNATURE; ++offset) {
bytes[offset] = baseImage[offset];
bytes[offset] = getBaseImage()[offset];
}
std::copy(imageSignature.begin(), imageSignature.end(), bytes.begin() + offset);
@ -140,7 +140,7 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
offset += imageSignature.length();
for (; offset < cfgHeader.base; ++offset) {
bytes[offset] = baseImage[offset];
bytes[offset] = getBaseImage()[offset];
}
bytes[offset++] = cfg.fileFormat;
@ -150,7 +150,7 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
bytes[offset++] = (cfg.length >> 4) & 0xFF;
for (; offset < cfgHeader.base + CFG_LENGTH; ++offset) {
bytes[offset] = baseImage[offset];
bytes[offset] = getBaseImage()[offset];
}
if (cfg.version == 0) {
@ -168,7 +168,7 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
bytes[offset] = 0xFF;
}
std::copy(baseImage.begin() + offset, baseImage.end(), bytes.begin() + offset);
std::copy(getBaseImage().begin() + offset, getBaseImage().end(), bytes.begin() + offset);
for (const auto &entry : instructions) {
auto data = entry.second->toBytes();
@ -180,17 +180,20 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
jumpTable.clear();
std::queue<AnalysisState> savedStates;
std::vector<AnalysisState> branchingStates;
std::unordered_map<uint32_t, bool> jumpsUsed;
AnalysisState baseState(offset);
AnalysisState baseState(offset, jumpTable);
savedStates.push(baseState);
uint32_t maxUnchangedExecutions = 1000;
uint32_t maxTotalExecutions = 20000;
uint32_t speculativeJumps = 0;
while (!savedStates.empty()) {
AnalysisState state = savedStates.front();
@ -201,6 +204,10 @@ void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
do {
if (jumpsUsed.find(state.current) != jumpsUsed.end() && !jumpsUsed[state.current]) {
speculativeJumps++;
}
jumpsUsed[state.current] = true;
if (state.current >= 0x100000 || (findInstructionByAddress(state.current) == nullptr &&
@ -209,7 +216,7 @@ void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
break;
} else if (findInstructionByAddress(state.current) == nullptr) {
auto decodedInstruction = Instruction::Instruction::decodeInstructionFromBytes(state.current,
baseImage);
getBaseImage());
instructions[decodedInstruction->getAddress()] = std::move(decodedInstruction);
}
@ -227,6 +234,10 @@ void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
auto possibleBranches = instruction->execute(state);
if (jumpsUsed.find(state.current) != jumpsUsed.end() && !jumpsUsed[state.current]) {
jumpsUsed.erase(state.current); //Clear to recognize a non-speculative jump
}
if ((instruction->getCommand() == Instruction::Instruction::CommandOp::JUMP ||
instruction->getCommand() == Instruction::Instruction::CommandOp::RETURN) &&
jumpsUsed.find(instruction->getEndAddress()) == jumpsUsed.end()) {
@ -268,7 +279,7 @@ void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
for (const auto &branch : possibleBranches) {
AnalysisState newState(state);
newState.current = branch.first & 0xfffffffc;
newState.current = branch.first;
for (const auto &entry : branch.second) {
newState.setRegister(entry.first, entry.second);
}
@ -293,6 +304,7 @@ void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
for (auto &visited : jumpsUsed) {
if (!visited.second && visited.first >= offset && visited.first <= 0x100000) {
baseState.current = visited.first;
baseState.addKnownJump(visited.first, 0, JumpKind::Speculative);
savedStates.push(baseState);
break;
}
@ -300,7 +312,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: "
<< /*", executed states: " << std::dec << createdStates.size() <<*/ ", speculative jumps: "
<< std::dec << speculativeJumps << ", total instructions decoded: "
<< std::dec << instructions.size() << "\n";
}
}

View file

@ -63,6 +63,30 @@ public:
void decodeAnalyzeInstructionsAt(uint32_t offset);
const std::unique_ptr<Instruction::Instruction> &
findConstInstructionByAddress(uint32_t addr, bool indirect = false) const {
if (instructions.find(addr) != instructions.end()) {
return instructions.find(addr)->second;
}
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;
}
}
}
return NULL_INSTRUCTION;
}
std::unique_ptr<Instruction::Instruction> &findInstructionByAddress(uint32_t addr, bool indirect = false) {
if (instructions.find(addr) != instructions.end()) {
return instructions.find(addr)->second;
@ -98,6 +122,10 @@ public:
return instructions;
}
const auto &getJumpTable() const {
return jumpTable;
}
const auto &getBaseImage() const {
return baseImage;
}
@ -145,4 +173,6 @@ private:
std::map<uint32_t, std::unique_ptr<Instruction::Instruction>> instructions;
std::vector<uint8_t> baseImage;
AnalysisJumpTable jumpTable;
};

199
src/OutputContext.cpp Normal file
View file

@ -0,0 +1,199 @@
/*****************************************************************************
* 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 <sstream>
#include <iomanip>
#include "OutputContext.h"
#include "instructions/Write.h"
#include "instructions/Jump.h"
#include "Registers.h"
std::string OutputContext::getLabel(uint32_t location, bool force) const {
if (mappings.find(location) != mappings.end() && (!force || !mappings.at(location).empty())) {
return mappings.at(location);
}
if (force) {
std::stringstream s;
s << "loc_" << std::hex << std::setw(6) << std::setfill('0') << location;
return s.str();
}
return "";
}
std::string OutputContext::getComment(uint32_t location) const {
if (comments.find(location) != comments.end()) {
return " ; " + comments.at(location);
}
return "";
}
std::string OutputContext::getDataHeader(uint32_t location) const {
std::stringstream s;
s << std::hex << std::setw(6) << std::setfill('0') << location << " ";
for (uint32_t i = location; i < location + 4; ++i) {
s << std::hex << std::setw(2) << std::setfill('0') << (uint32_t) image.getBaseImage().at(i) << " ";
}
s << " ";
return s.str();
}
std::string OutputContext::getDataEntry(uint32_t location, const std::string &representation) const {
std::string result = getDataHeader(location) + representation;
uint32_t padLength = 80;
if (result.size() < padLength) {
result.append(padLength - result.size(), ' ');
}
result += getComment(location);
return result;
}
std::string OutputContext::getInstructionString(const Instruction::Instruction &instruction) const {
std::string output;
for (auto &l : instruction.toOutputFormat(*this)) {
output += getDataEntry(l.location, l.format) + "\n";
}
return output;
}
void OutputContext::analyze() {
const auto &table = image.getJumpTable();
for (auto &e : table) {
std::stringstream from;
from << "XREF.CallFrom: ";
bool hasContinue = false;
bool justAbsolute = true;
bool justReturn = true;
for (auto &j : e.second) {
if (j.second != JumpKind::Return && j.second != JumpKind::Speculative) {
justReturn = false;
}
if (j.second != JumpKind::Absolute && j.second != JumpKind::Speculative) {
justAbsolute = false;
}
if (j.second != JumpKind::Continue) {
from << std::hex << std::setw(6) << std::setfill('0') << j.first << "(";
switch (j.second) {
case JumpKind::Speculative:
from << "Speculative";
break;
case JumpKind::Absolute:
from << "Absolute";
break;
case JumpKind::Branch:
from << "Branch";
break;
case JumpKind::Loop:
from << "Loop";
break;
case JumpKind::Return:
from << "Return";
break;
}
from << "), ";
} else {
hasContinue = true;
}
}
if (justReturn || justAbsolute) {
if (!e.second.empty() && justReturn) {
auto &instruction = image.findConstInstructionByAddress(e.first - 1, true);
if (instruction != nullptr && (instruction->getCommand() == Instruction::Instruction::CommandOp::JUMP ||
instruction->getCommand() ==
Instruction::Instruction::CommandOp::RETURN)) {
std::string locText = "RETURN location for call";
bool foundReturn = false;
uint32_t addressLocation = instruction->getAddress() - 1;
if (instruction->getCommand() == Instruction::Instruction::CommandOp::JUMP) {
auto &jumpInstruction = dynamic_cast<const Instruction::Jump &>(*instruction);
locText = "RETURN location for " + getLabel(jumpInstruction.jumpAddress);
}
while (true) {
auto &instructionBefore = image.findConstInstructionByAddress(addressLocation, true);
if (instructionBefore != nullptr &&
instructionBefore->getCommand() == Instruction::Instruction::CommandOp::WRITE) {
auto &writeInstruction = dynamic_cast<const Instruction::Write &>(*instructionBefore);
if (writeInstruction.data.size() == 1 &&
writeInstruction.data[0] == e.first) { //Return value!
//TODO: mark join?
addComment(writeInstruction.getAddress() + 4, locText);
foundReturn = true;
break;
}
addressLocation = instructionBefore->getAddress() - 1;
} else {
break;
}
}
if (!foundReturn) {
addMapping(e.first, getLabel(e.first, true));
}
} else {
addMapping(e.first, getLabel(e.first, true));
}
} else {
addMapping(e.first, getLabel(e.first, true));
}
}
if (e.second.size() > 1 || (!hasContinue && !e.second.empty())) {
addComment(e.first, "<" + getLabel(e.first, true) + "> " + from.str());
}
}
}
void OutputContext::addMapping(uint32_t location, const std::string &name, bool force) {
if (mappings.find(location) == comments.end() || (force && !mappings[location].empty())) {
mappings[location] = name;
}
}
void OutputContext::addComment(uint32_t location, const std::string &comment) {
if (comments.find(location) != comments.end()) {
comments[location] = comment + " --- " + comments[location];
} else {
comments[location] = comment;
}
}
std::string OutputContext::getAddressRegisterName(uint32_t addr, uint8_t offset) const {
if (offset || registers.find(addr) == registers.end()) {
return ::getAddressRegisterName(addr, offset);
} else {
return registers.at(addr);
}
}

77
src/OutputContext.h Normal file
View file

@ -0,0 +1,77 @@
/*****************************************************************************
* 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 <cstdint>
#include <unordered_map>
#include <vector>
#include <algorithm>
#include "ImageFormat.h"
class OutputContext {
public:
private:
const ImageFormat &image;
std::unordered_map<uint32_t, std::string> mappings;
std::unordered_map<uint32_t, std::string> comments;
std::unordered_map<uint32_t, std::string> registers;
public:
OutputContext(const ImageFormat &image) : image(image) {
}
void addMapping(uint32_t location, const std::string &name, bool force = false);
void addComment(uint32_t location, const std::string &comment);
void addRegister(uint32_t addr, const std::string &name) {
registers[addr] = name;
}
std::string getAddressRegisterName(uint32_t addr, uint8_t offset) const;
std::string getAddressRegisterName(const Instruction::AddressWithOffset &address) const {
return getAddressRegisterName(address.address, address.offset);
}
std::string getLabel(uint32_t location, bool force = true) const;
std::string getComment(uint32_t location) const;
std::string getDataHeader(uint32_t location) const;
std::string getDataEntry(uint32_t location, const std::string &representation = "") const;
std::string getInstructionString(const Instruction::Instruction &instruction) const;
void analyze();
};

View file

@ -144,8 +144,10 @@ std::string getRegisterName(KnownRegisters addr) {
return "REI_CTRL";
case KnownRegisters::REI_STAT:
return "REI_STAT";
case KnownRegisters::BIST_CTRL:
return "BIST_CTRL";
case KnownRegisters::BIST_CTRL_0:
return "BIST_CTRL[0]";
case KnownRegisters::BIST_CTRL_1:
return "BIST_CTRL[1]";
case KnownRegisters::PCIE_CLKMON_RATIO_CFG:
return "PCIE_CLKMON_RATIO_CFG";
case KnownRegisters::PCIE_CLKMON_TOLERANCE_CFG:
@ -180,6 +182,10 @@ std::string getAddressRegisterName(uint32_t addr, uint8_t offset) {
return s.str();
}
std::string getAddressRegisterName(const Instruction::AddressWithOffset &address) {
return getAddressRegisterName(address.address, address.offset);
}
KnownRegisters getScratchRegister(uint32_t offset) {
return static_cast<KnownRegisters>((uint32_t) KnownRegisters::BSM_SCRATCH_START + offset);
}

View file

@ -30,6 +30,7 @@
#include <cstdint>
#include <string>
#include "instructions/AddressOffset.h"
enum class KnownRegisters : uint32_t {
PCIE_MASTER_SPICO_FIRMWARE_SPECIAL_REGISTER = 0x0,
@ -66,7 +67,8 @@ enum class KnownRegisters : uint32_t {
BSM_COUNTER_0 = 0x000C08,
BSM_COUNTER_1 = BSM_COUNTER_0 + 1,
BIST_CTRL = 0x000C10,
BIST_CTRL_0 = 0x000C10,
BIST_CTRL_1 = 0x000C11,
REI_CTRL = 0x000C12,
REI_STAT = 0x000C13,
@ -124,4 +126,6 @@ KnownRegisters getScratchRegister(uint32_t offset);
std::string getRegisterName(KnownRegisters addr);
std::string getAddressRegisterName(uint32_t addr, uint8_t offset = 0);
std::string getAddressRegisterName(uint32_t addr, uint8_t offset = 0);
std::string getAddressRegisterName(const Instruction::AddressWithOffset &address);

View file

@ -0,0 +1,35 @@
/*****************************************************************************
* 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
namespace Instruction {
typedef struct {
uint32_t address: 24;
uint8_t offset: 2;
} AddressWithOffset;
}

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Branch::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -36,11 +37,11 @@ void Instruction::Branch::fromBytes(uint32_t offset, const std::vector<uint8_t>
uint32_t command = bytes[offset++];
equality = (command >> 2) & 0b1;
addressOffset = command & 0b11;
address.offset = command & 0b11;
address = bytes[offset++] << 16;
address |= bytes[offset++] << 8;
address |= bytes[offset++];
address.address = bytes[offset++] << 16;
address.address |= bytes[offset++] << 8;
address.address |= bytes[offset++];
value = bytes[offset++] << 24;
value |= bytes[offset++] << 16;
@ -64,7 +65,7 @@ void Instruction::Branch::fromBytes(uint32_t offset, const std::vector<uint8_t>
std::string Instruction::Branch::toString() const {
std::stringstream op;
op << "BRANCH IF (" << getAddressRegisterName(address, addressOffset) << " & 0x" << std::hex << std::setw(8)
op << "BRANCH IF (" << getAddressRegisterName(address) << " & 0x" << std::hex << std::setw(8)
<< std::setfill('0') << mask << ")";
if (equality) {
op << " == ";
@ -77,6 +78,28 @@ std::string Instruction::Branch::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Branch::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream &>(std::stringstream("") << "BRANCH" << " "
<< context.getAddressRegisterName(
address)
<< (equality ? " == "
: " != ")).str()},
OutputFormat{getAddress() + 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << " VALUE 0x" << std::hex
<< std::setw(8) << std::setfill('0')
<< value).str()},
OutputFormat{getAddress() + 8,
dynamic_cast<std::stringstream &>(std::stringstream("") << " MASK 0x" << std::hex
<< std::setw(8) << std::setfill('0')
<< mask).str()},
OutputFormat{getAddress() + 12,
dynamic_cast<std::stringstream &>(std::stringstream("") << " JUMP_ADDRESS <"
<< context.getLabel(jumpAddress)
<< ">").str()},
};
}
std::vector<uint32_t> Instruction::Branch::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress, jumpAddress};
}
@ -85,35 +108,37 @@ 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(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[state.getAddressWithOffset(address)] =
state.getRegister(address) | (equality ? ~value & mask : value);
branches.emplace_back(equality ? _endAddress : jumpAddress, std::move(branchedState));
} 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[state.getAddressWithOffset(address)] =
state.getRegister(address) | (equality ? value : ~value & mask);
branches.emplace_back(equality ? jumpAddress : _endAddress, std::move(branchedState));
}
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
state.addKnownJump(jumpAddress, getAddress(), JumpKind::Branch);
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((uint8_t) getCommand() | (equality << 2) | address.offset);
bytes.emplace_back((address >> 16) & 0xFF);
bytes.emplace_back((address >> 8) & 0xFF);
bytes.emplace_back(address & 0xFF);
bytes.emplace_back((address.address >> 16) & 0xFF);
bytes.emplace_back((address.address >> 8) & 0xFF);
bytes.emplace_back(address.address & 0xFF);
bytes.emplace_back((value >> 24) & 0xFF);
bytes.emplace_back((value >> 16) & 0xFF);

View file

@ -46,15 +46,16 @@ namespace Instruction {
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext &context) const override;
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;
uint8_t addressOffset;
uint8_t equality;
uint32_t address;
AddressWithOffset address;
uint32_t value;
uint32_t mask;
uint32_t jumpAddress;

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Calc::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -92,6 +93,51 @@ std::string Instruction::Calc::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Calc::toOutputFormat(const OutputContext &context) const {
std::stringstream opname;
switch (operation) {
case Operation::AND:
opname << "AND";
break;
case Operation::OR:
opname << "OR";
break;
case Operation::ADD:
opname << "ADD";
break;
case Operation::SUB:
opname << "SUB";
break;
case Operation::LSHIFT:
opname << "LSHIFT";
break;
case Operation::RSHIFT:
opname << "RSHIFT";
break;
case Operation::ARSHIFT:
opname << "ARSHIFT";
break;
case Operation::UNDEFINED:
opname << "UNDEFINED";
break;
}
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream &>(opname << " "
<< context.getAddressRegisterName(
addressDestination,
addressOffset) << " = ").str()},
OutputFormat{getAddress() + 4, dynamic_cast<std::stringstream &>(std::stringstream("") << " SOURCE "
<< context.getAddressRegisterName(
addressSource,
addressOffset)).str()},
OutputFormat{getAddress() + 8, dynamic_cast<std::stringstream &>(std::stringstream("") << " TARGET "
<< context.getAddressRegisterName(
addressTarget,
addressOffset)).str()},
};
}
std::vector<uint32_t> Instruction::Calc::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress};
}
@ -132,6 +178,8 @@ Instruction::Calc::execute(AnalysisState &state) const {
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}

View file

@ -58,6 +58,8 @@ namespace Instruction {
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext &context) const override;
std::vector<uint32_t> getPossibleBranches() const override;
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::CalcImm::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -92,6 +93,51 @@ std::string Instruction::CalcImm::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::CalcImm::toOutputFormat(const OutputContext &context) const {
std::stringstream opname;
switch (operation) {
case Calc::Operation::AND:
opname << "AND";
break;
case Calc::Operation::OR:
opname << "OR";
break;
case Calc::Operation::ADD:
opname << "ADD";
break;
case Calc::Operation::SUB:
opname << "SUB";
break;
case Calc::Operation::LSHIFT:
opname << "LSHIFT";
break;
case Calc::Operation::RSHIFT:
opname << "RSHIFT";
break;
case Calc::Operation::ARSHIFT:
opname << "ARSHIFT";
break;
case Calc::Operation::UNDEFINED:
opname << "UNDEFINED";
break;
}
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream &>(opname << "_IMM "
<< context.getAddressRegisterName(
addressDestination,
addressOffset) << " = ").str()},
OutputFormat{getAddress() + 4, dynamic_cast<std::stringstream &>(std::stringstream("") << " SOURCE "
<< context.getAddressRegisterName(
addressSource,
addressOffset)).str()},
OutputFormat{getAddress() + 8,
dynamic_cast<std::stringstream &>(std::stringstream("") << " TARGET 0x" << std::hex
<< std::setw(8) << std::setfill('0')
<< value).str()},
};
}
std::vector<uint32_t> Instruction::CalcImm::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress};
}
@ -131,6 +177,8 @@ Instruction::CalcImm::execute(AnalysisState &state) const {
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}

View file

@ -48,6 +48,8 @@ namespace Instruction {
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext &context) const override;
std::vector<uint32_t> getPossibleBranches() const override;
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Copy::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -36,18 +37,18 @@ void Instruction::Copy::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
uint32_t command = bytes[offset++];
count = (1 + ((command >> 4) & 0b11));
addressOffsetBB = (command >> 2) & 0b11;
addressOffsetAA = command & 0b11;
addressBB.offset = (command >> 2) & 0b11;
addressAA.offset = command & 0b11;
addressAA = bytes[offset++] << 16;
addressAA |= bytes[offset++] << 8;
addressAA |= bytes[offset++];
addressAA.address = bytes[offset++] << 16;
addressAA.address |= bytes[offset++] << 8;
addressAA.address |= bytes[offset++];
offset++;
addressBB = bytes[offset++] << 16;
addressBB |= bytes[offset++] << 8;
addressBB |= bytes[offset++];
addressBB.address = bytes[offset++] << 16;
addressBB.address |= bytes[offset++] << 8;
addressBB.address |= bytes[offset++];
_endAddress = offset;
@ -56,11 +57,24 @@ void Instruction::Copy::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
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);
<< getAddressRegisterName(addressAA) << " TO "
<< getAddressRegisterName(addressBB);
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Copy::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(),
dynamic_cast<std::stringstream &>(std::stringstream("") << "COPY" << " " << std::dec
<< (uint32_t) count << ", "
<< context.getAddressRegisterName(
addressAA)).str()},
OutputFormat{getAddress() + 4, dynamic_cast<std::stringstream &>(std::stringstream("") << " TO "
<< context.getAddressRegisterName(
addressBB)).str()}
};
}
std::vector<uint32_t> Instruction::Copy::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress};
}
@ -68,15 +82,15 @@ std::vector<uint32_t> Instruction::Copy::getPossibleBranches() 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) {
state.setRegister(memoryOffsetAA + addressOffsetAA + i, state.getRegister(memoryOffsetBB + addressBB));
state.setRegister(addressBB.offset + addressBB.address + i,
state.getRegister(addressAA.offset + addressAA.address + i));
}
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}
@ -84,17 +98,17 @@ Instruction::Copy::execute(AnalysisState &state) const {
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) | (addressBB.offset << 2) | addressAA.offset);
bytes.emplace_back((addressAA >> 16) & 0xFF);
bytes.emplace_back((addressAA >> 8) & 0xFF);
bytes.emplace_back(addressAA & 0xFF);
bytes.emplace_back((addressAA.address >> 16) & 0xFF);
bytes.emplace_back((addressAA.address >> 8) & 0xFF);
bytes.emplace_back(addressAA.address & 0xFF);
bytes.emplace_back(0);
bytes.emplace_back((addressBB >> 16) & 0xFF);
bytes.emplace_back((addressBB >> 8) & 0xFF);
bytes.emplace_back(addressBB & 0xFF);
bytes.emplace_back((addressBB.address >> 16) & 0xFF);
bytes.emplace_back((addressBB.address >> 8) & 0xFF);
bytes.emplace_back(addressBB.address & 0xFF);
return bytes;
}

View file

@ -46,6 +46,8 @@ namespace Instruction {
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext &context) const override;
std::vector<uint32_t> getPossibleBranches() const override;
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
@ -53,9 +55,7 @@ namespace Instruction {
uint8_t count;
uint8_t addressOffsetBB;
uint8_t addressOffsetAA;
uint32_t addressAA;
uint32_t addressBB;
AddressWithOffset addressAA;
AddressWithOffset addressBB;
};
}

View file

@ -26,6 +26,8 @@
*****************************************************************************/
#include "End.h"
#include <iostream>
#include <iomanip>
void Instruction::End::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -43,6 +45,12 @@ std::string Instruction::End::toString() const {
return "END";
}
std::vector<Instruction::OutputFormat> Instruction::End::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), "END"}
};
}
std::vector<uint32_t> Instruction::End::getPossibleBranches() const {
return std::vector<uint32_t>();
}

View file

@ -46,6 +46,8 @@ namespace Instruction {
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext &context) const override;
std::vector<uint32_t> getPossibleBranches() const override;
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>

View file

@ -77,6 +77,12 @@ std::string Instruction::Init::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Init::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
//TODO
};
}
std::vector<uint32_t> Instruction::Init::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress};
}
@ -89,6 +95,8 @@ Instruction::Init::execute(AnalysisState &state) const {
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}

View file

@ -46,6 +46,8 @@ namespace Instruction {
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext &context) const override;
std::vector<uint32_t> getPossibleBranches() const override;
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>

View file

@ -34,7 +34,13 @@
#include <memory>
#include "../AnalysisState.h"
class OutputContext;
namespace Instruction {
typedef struct {
uint32_t location;
std::string format;
} OutputFormat;
class Instruction {
protected:
@ -42,18 +48,6 @@ namespace Instruction {
uint32_t _endAddress{};
public:
/*Instruction(){
}
*/
/*
Instruction(const Instruction& instruction) : address(instruction.address), endAddress(instruction.endAddress), command(instruction.command), parameters(instruction.parameters){
}
*/
enum class CommandOp : uint8_t {
WRITE = 0b00000000,
COPY = 0b01000000,
@ -76,17 +70,14 @@ namespace Instruction {
static CommandOp getCommandFromByte(uint8_t command);
/*
Instruction(uint32_t address, uint32_t command, std::vector<uint32_t> parameters) : address(address), command(command), parameters(std::move(parameters)), endAddress(0){
}*/
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<OutputFormat> toOutputFormat(const OutputContext &context) const = 0;
virtual std::vector<uint32_t> getPossibleBranches() const = 0;
virtual std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Jump::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -50,6 +51,15 @@ std::string Instruction::Jump::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Jump::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream &>(std::stringstream("") << "JUMP" << " <"
<< context.getLabel(
jumpAddress)
<< ">").str()}
};
}
std::vector<uint32_t> Instruction::Jump::getPossibleBranches() const {
return std::vector<uint32_t>{jumpAddress};
}
@ -58,6 +68,8 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
Instruction::Jump::execute(AnalysisState &state) const {
state.current = jumpAddress;
state.addKnownJump(jumpAddress, getAddress(), JumpKind::Absolute);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}

View file

@ -46,6 +46,8 @@ namespace Instruction {
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext &context) const override;
std::vector<uint32_t> getPossibleBranches() const override;
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Load::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -111,6 +112,91 @@ std::string Instruction::Load::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Load::toOutputFormat(const OutputContext &context) const {
if (addressOffset == 0 && increment == 0 &&
address == (uint32_t) KnownRegisters::PCIE_MASTER_SPICO_FIRMWARE_SPECIAL_REGISTER) {
uint32_t offset = 0;
std::vector<OutputFormat> f{
OutputFormat{getAddress() + offset++ * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << "LOAD"
<< " PCIE_MASTER_SPICO_FIRMWARE").str()}
};
f.emplace_back(OutputFormat{getAddress() + offset++ * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << " COUNT " << std::dec
<< data.size()).str()});
for (auto d : data) {
f.emplace_back(OutputFormat{getAddress() + offset * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << " 0x" << std::hex
<< std::setw(8)
<< std::setfill('0')
<< d).str()});
offset++;
}
return f;
} else if (addressOffset == 0 && increment == 0 &&
address == (uint32_t) KnownRegisters::PCIE_BROADCAST_SERDES_FIRMWARE_SPECIAL_REGISTER) {
uint32_t offset = 0;
std::vector<OutputFormat> f{
OutputFormat{getAddress() + offset++ * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << "LOAD"
<< " PCIE_BROADCAST_SERDES_FIRMWARE").str()},
};
f.emplace_back(OutputFormat{getAddress() + offset++ * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << " COUNT " << std::dec
<< data.size()).str()});
for (auto d : data) {
f.emplace_back(OutputFormat{getAddress() + offset * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << " 0x" << std::hex
<< std::setw(8)
<< std::setfill('0')
<< d).str()});
offset++;
}
return f;
} else {
uint32_t offset = 0;
std::vector<OutputFormat> f{
OutputFormat{getAddress() + offset++ * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << "LOAD" << " "
<< context.getAddressRegisterName(
address, addressOffset)
<< ", INC " << std::dec
<< (uint32_t) increment).str()}
};
f.emplace_back(OutputFormat{getAddress() + offset++ * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << " COUNT " << std::dec
<< data.size()).str()});
for (auto d : data) {
f.emplace_back(OutputFormat{getAddress() + offset * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << " "
<< context.getAddressRegisterName(
address +
offset - 2,
addressOffset)
<< " = 0x" << std::hex
<< std::setw(8)
<< std::setfill('0')
<< d).str()});
offset++;
}
return f;
}
}
std::vector<uint32_t> Instruction::Load::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress};
}
@ -132,6 +218,8 @@ Instruction::Load::execute(AnalysisState &state) const {
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}

View file

@ -46,6 +46,8 @@ namespace Instruction {
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext &context) const override;
std::vector<uint32_t> getPossibleBranches() const override;
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Loop::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -52,6 +53,19 @@ std::string Instruction::Loop::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Loop::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream &>(std::stringstream("") << "LOOP" << " "
<< context.getAddressRegisterName(
(uint32_t) KnownRegisters::BSM_COUNTER_0 +
counter, 0)
<< ", <"
<< context.getLabel(
jumpAddress)
<< ">").str()},
};
}
std::vector<uint32_t> Instruction::Loop::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress, jumpAddress};
}
@ -77,6 +91,9 @@ Instruction::Loop::execute(AnalysisState &state) const {
branches.emplace_back(_endAddress, std::move(branchedState));
}
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
state.addKnownJump(jumpAddress, getAddress(), JumpKind::Loop);
return branches;
}

View file

@ -46,6 +46,8 @@ namespace Instruction {
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext &context) const override;
std::vector<uint32_t> getPossibleBranches() const override;
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Poll::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -36,11 +37,11 @@ void Instruction::Poll::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
uint32_t command = bytes[offset++];
equality = (command >> 2) & 0b1;
addressOffset = command & 0b11;
address.offset = command & 0b11;
address = bytes[offset++] << 16;
address |= bytes[offset++] << 8;
address |= bytes[offset++];
address.address = bytes[offset++] << 16;
address.address |= bytes[offset++] << 8;
address.address |= bytes[offset++];
value = bytes[offset++] << 24;
value |= bytes[offset++] << 16;
@ -70,7 +71,7 @@ void Instruction::Poll::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
std::string Instruction::Poll::toString() const {
std::stringstream op;
op << "POLL IF (" << getAddressRegisterName(address, addressOffset) << " & 0x" << std::hex << std::setw(8)
op << "POLL IF (" << getAddressRegisterName(address) << " & 0x" << std::hex << std::setw(8)
<< std::setfill('0') << mask << ")";
if (equality) {
op << " != ";
@ -84,6 +85,32 @@ std::string Instruction::Poll::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Poll::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream &>(std::stringstream("") << "POLL" << " "
<< context.getAddressRegisterName(
address)
<< (equality ? " == "
: " != ")).str()},
OutputFormat{getAddress() + 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << " VALUE 0x" << std::hex
<< std::setw(8) << std::setfill('0')
<< value).str()},
OutputFormat{getAddress() + 8,
dynamic_cast<std::stringstream &>(std::stringstream("") << " MASK 0x" << std::hex
<< std::setw(8) << std::setfill('0')
<< mask).str()},
OutputFormat{getAddress() + 12,
dynamic_cast<std::stringstream &>(std::stringstream("") << " RETRY MAX " << std::dec
<< maxRetry << " INTERVAL " << std::dec
<< retryInterval).str()},
OutputFormat{getAddress() + 16,
dynamic_cast<std::stringstream &>(std::stringstream("") << " JUMP_ADDRESS <"
<< context.getLabel(jumpAddress)
<< ">").str()},
};
}
std::vector<uint32_t> Instruction::Poll::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress, jumpAddress};
}
@ -92,35 +119,36 @@ 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(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[state.getAddressWithOffset(address)] =
state.getRegister(address) | (equality ? value : ~value & mask);
branches.emplace_back(equality ? jumpAddress : _endAddress, std::move(branchedState));
} 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[state.getAddressWithOffset(address)] =
state.getRegister(address) | (equality ? ~value & mask : value);
branches.emplace_back(equality ? _endAddress : jumpAddress, std::move(branchedState));
}
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
state.addKnownJump(jumpAddress, getAddress(), JumpKind::Branch);
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((uint8_t) getCommand() | (equality << 2) | address.offset);
bytes.emplace_back((address >> 16) & 0xFF);
bytes.emplace_back((address >> 8) & 0xFF);
bytes.emplace_back(address & 0xFF);
bytes.emplace_back((address.address >> 16) & 0xFF);
bytes.emplace_back((address.address >> 8) & 0xFF);
bytes.emplace_back(address.address & 0xFF);
bytes.emplace_back((value >> 24) & 0xFF);
bytes.emplace_back((value >> 16) & 0xFF);

View file

@ -46,15 +46,16 @@ namespace Instruction {
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext &context) const override;
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;
uint8_t addressOffset;
uint8_t equality;
uint32_t address;
AddressWithOffset address;
uint32_t value;
uint32_t mask;
uint16_t maxRetry;

View file

@ -29,17 +29,18 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Return::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
uint8_t command = bytes[offset++];
addressOffset = command & 0b11;
address.offset = command & 0b11;
address = bytes[offset++] << 16;
address |= bytes[offset++] << 8;
address |= bytes[offset++];
address.address = bytes[offset++] << 16;
address.address |= bytes[offset++] << 8;
address.address |= bytes[offset++];
_endAddress = offset;
@ -47,22 +48,31 @@ void Instruction::Return::fromBytes(uint32_t offset, const std::vector<uint8_t>
std::string Instruction::Return::toString() const {
std::stringstream op;
op << "RETURN " << getAddressRegisterName(address, addressOffset);
op << "RETURN " << getAddressRegisterName(address);
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Return::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream &>(std::stringstream("") << "RETURN" << " ["
<< context.getAddressRegisterName(
address)
<< "]").str()}
};
}
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 {
uint32_t memoryOffset = state.getAddressOffset(addressOffset);
uint32_t jumpAddress = state.getRegister(memoryOffset + address);
uint32_t jumpAddress = state.getRegister(address);
state.current = jumpAddress;
state.addKnownJump(jumpAddress, getAddress(), JumpKind::Return);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}
@ -70,11 +80,11 @@ Instruction::Return::execute(AnalysisState &state) const {
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() | address.offset);
bytes.emplace_back((address >> 16) & 0xFF);
bytes.emplace_back((address >> 8) & 0xFF);
bytes.emplace_back(address & 0xFF);
bytes.emplace_back((address.address >> 16) & 0xFF);
bytes.emplace_back((address.address >> 8) & 0xFF);
bytes.emplace_back(address.address & 0xFF);
return bytes;
}

View file

@ -46,12 +46,13 @@ namespace Instruction {
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext &context) const override;
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;
uint8_t addressOffset;
uint32_t address;
AddressWithOffset address;
};
}

View file

@ -29,17 +29,18 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Set::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
uint8_t command = bytes[offset++];
addressOffset = command & 0b11;
address.offset = command & 0b11;
address = bytes[offset++] << 16;
address |= bytes[offset++] << 8;
address |= bytes[offset++];
address.address = bytes[offset++] << 16;
address.address |= bytes[offset++] << 8;
address.address |= bytes[offset++];
value = bytes[offset++] << 24;
value |= bytes[offset++] << 16;
@ -57,35 +58,51 @@ void Instruction::Set::fromBytes(uint32_t offset, const std::vector<uint8_t> &by
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')
op << "SET " << getAddressRegisterName(address) << " = ("
<< getAddressRegisterName(address) << " & ~0x" << std::hex << std::setw(8) << std::setfill('0')
<< mask << ") | " << "0x" << std::hex << std::setw(8) << std::setfill('0') << value;
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Set::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream &>(std::stringstream("") << "SET" << " "
<< context.getAddressRegisterName(
address)).str()},
OutputFormat{getAddress() + 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << " VALUE 0x" << std::hex
<< std::setw(8) << std::setfill('0')
<< value).str()},
OutputFormat{getAddress() + 8,
dynamic_cast<std::stringstream &>(std::stringstream("") << " MASK 0x" << std::hex
<< std::setw(8) << std::setfill('0')
<< mask).str()}
};
}
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 {
uint32_t memoryOffset = state.getAddressOffset(addressOffset);
state.setRegister(memoryOffset + address, (state.getRegister(memoryOffset + address) & ~mask) | value);
state.setRegister(address, (state.getRegister(address) & ~mask) | value);
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
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((uint8_t) getCommand() | address.offset);
bytes.emplace_back((address >> 16) & 0xFF);
bytes.emplace_back((address >> 8) & 0xFF);
bytes.emplace_back(address & 0xFF);
bytes.emplace_back((address.address >> 16) & 0xFF);
bytes.emplace_back((address.address >> 8) & 0xFF);
bytes.emplace_back(address.address & 0xFF);
bytes.emplace_back((value >> 24) & 0xFF);
bytes.emplace_back((value >> 16) & 0xFF);

View file

@ -46,13 +46,14 @@ namespace Instruction {
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext &context) const override;
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;
uint8_t addressOffset;
uint32_t address;
AddressWithOffset address;
uint32_t value;
uint32_t mask;
};

View file

@ -50,6 +50,14 @@ std::string Instruction::Wait::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Wait::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(),
dynamic_cast<std::stringstream &>(std::stringstream("") << "WAIT" << " " << std::dec
<< time).str()}
};
}
std::vector<uint32_t> Instruction::Wait::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress};
}
@ -60,6 +68,8 @@ Instruction::Wait::execute(AnalysisState &state) const {
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}

View file

@ -46,6 +46,8 @@ namespace Instruction {
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext &context) const override;
std::vector<uint32_t> getPossibleBranches() const override;
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Write::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -64,6 +65,35 @@ std::string Instruction::Write::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Write::toOutputFormat(const OutputContext &context) const {
uint32_t offset = 0;
std::vector<OutputFormat> f{
OutputFormat{getAddress() + offset++ * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << "WRITE" << " "
<< context.getAddressRegisterName(
address, addressOffset) << ", "
<< std::dec
<< (uint32_t) data.size()).str()}
};
for (auto d : data) {
f.emplace_back(OutputFormat{getAddress() + offset * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << " "
<< context.getAddressRegisterName(
address + offset -
1, addressOffset)
<< " = 0x" << std::hex
<< std::setw(8)
<< std::setfill('0')
<< d).str()});
offset++;
}
return f;
}
std::vector<uint32_t> Instruction::Write::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress};
}
@ -78,6 +108,10 @@ Instruction::Write::execute(AnalysisState &state) const {
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}

View file

@ -34,12 +34,6 @@
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() {
}
@ -54,6 +48,8 @@ namespace Instruction {
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext &context) const override;
std::vector<uint32_t> getPossibleBranches() const override;
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>

View file

@ -33,6 +33,7 @@
#include "ImageFormat.h"
#include "Registers.h"
#include "instructions/Load.h"
#include "OutputContext.h"
void decodeImage(const std::string &fileName) {
@ -54,21 +55,277 @@ void decodeImage(const std::string &fileName) {
std::cout << k << "\n";
}
OutputContext ctx(imageObject);
std::unordered_map<uint32_t, std::string> knownNames{
{0x1000, "load_bootCfg_pep_serialNumber"},
{0x1054, "load_bootCfg_customMac"},
{0x080600, "config_systimeClockSource"},
{0x080700, "config_startClocks"},
{0x080800, "config_pcie_pep_modes"},
{0x080900, "config_pcie_pep_enable"},
{0x083000, "config_?serdes?_pep"},
{0x084000, "reset_BSM_ARGS_init__ENTRYPOINT"},
{0x085a0c, "config_pep0_offsets"},
{0x085a58, "config_pep1_offsets"},
{0x085aa4, "config_pep2_offsets"},
{0x085af0, "config_pep3_offsets"},
{0x085b3c, "config_pep4_offsets"},
{0x085b88, "config_pep5_offsets"},
{0x085bd4, "config_pep6_offsets"},
{0x085c20, "config_pep7_offsets"},
{0x085c6c, "config_pep8_offsets"},
{0x088000, "load_bootCfg_pep0_vpd"},
{0x0881c7, "load_bootCfg_pep1_vpd"},
{0x08838e, "load_bootCfg_pep2_vpd"},
{0x088555, "load_bootCfg_pep3_vpd"},
{0x08871c, "load_bootCfg_pep4_vpd"},
{0x0888e3, "load_bootCfg_pep5_vpd"},
{0x088aaa, "load_bootCfg_pep6_vpd"},
{0x088c71, "load_bootCfg_pep7_vpd"},
{0x088e38, "load_bootCfg_pep8_vpd"},
{0x089000, "load_bootCfg_systimeClockSource"},
{0x089010, "load_bootCfg_pep0_mode"},
{0x089020, "load_bootCfg_pep2_mode"},
{0x089030, "load_bootCfg_pep4_mode"},
{0x089040, "load_bootCfg_pep6_mode"},
{0x089050, "load_bootCfg_pep0_enable"},
{0x089060, "load_bootCfg_pep1_enable"},
{0x089070, "load_bootCfg_pep2_enable"},
{0x089080, "load_bootCfg_pep3_enable"},
{0x089090, "load_bootCfg_pep4_enable"},
{0x0890a0, "load_bootCfg_pep5_enable"},
{0x0890b0, "load_bootCfg_pep6_enable"},
{0x0890c0, "load_bootCfg_pep7_enable"},
{0x0890d0, "load_bootCfg_pep8_enable"},
{0x0890e0, "load_bootCfg_GPIO_PIN14_DRIVE"},
{0x0890f0, "load_bootCfg_spiTransferMode"},
{0x089100, "load_bootCfg_spiTransferSpeed"},
{0x089120, "load_bootCfg_skipPcieInitialization"},
{0x089130, "load_bootCfg_pep_numberOfLanes"},
{0x0891f0, "load_bootCfg_pep_mgmtPep"},
{0x089230, "load_bootCfg_pep_vendor_device"},
{0x089260, "load_bootCfg_pep_subVendor_subDevice"},
{0x0892f0, "load_bootCfg_pep_gen"},
{0x089380, "load_bootCfg_pep_ASPMEnable"},
{0x0839fc, "lock_PCIE_SBUS_take"},
{0x083aac, "lock_PCIE_SBUS_release"},
{0x083900, "execute_SerialBus_PCIE_Command"},
{0x080b00, "mark_SOFT_RESET_ClocksStable_ColdReset"},
{0x081100, "init_MASTER_SPICO"},
{0x0812ac, "FAIL_init_MASTER_SPICO"},
{0x08a004, "load_MASTER_SPICO_FW"},
{0x081400, "init_SERDES"},
{0x081b8c, "FAIL_init_SERDES"},
{0x08c004, "load_SERDES_FW"},
//Merge function
{0x080004, ""},
{0x080008, ""},
{0x08000c, ""},
{0x08001c, ""},
{0x080038, ""},
{0x080068, ""},
{0x0870c4, ""},
//Unknown
{0x089110, "loc_089110_load_config_unknown_1"},
{0x089160, "loc_089160_load_config_unknown_9"},
{0x089190, "loc_089190_load_config_unknown_9"},
{0x0891c0, "loc_0891c0_load_config_unknown_9"},
{0x089220, "load_eeprom_major_version"},
{0x089290, "loc_089290_load_config_unknown_9"},
{0x0892c0, "loc_0892c0_load_config_unknown_9"},
{0x089320, "loc_089320_load_config_unknown_9"},
{0x089350, "loc_089350_load_config_unknown_9"},
{0x0893b0, "load_bootCfg_skipPcieInitialization_skipMemRepair"},
{0x080d00, "config_memRepair"},
{0x0893c0, "load_pcie_clkmon_settings"},
};
knownNames[imageObject.getHeader().baseAddress] = "__ENTRYPOINT";
std::unordered_map<uint32_t, std::string> comments{
{0x080260, "Setting BSM_ARGS means this will be called again when reset, BSM_SCRATCH[0x149] is set to ~ 084000"},
{0x084000, "XREF From BSM_ARGS"},
{0x080800, "Reset DEVICE_CFG to all 0"},
{0x080828, "set DEVICE_CFG.PCIeMode[0] to 1x8 (default 2x4)"},
{0x080850, "set DEVICE_CFG.PCIeMode[1] to 1x8 (default 2x4)"},
{0x080878, "set DEVICE_CFG.PCIeMode[2] to 1x8 (default 2x4)"},
{0x0808a0, "set DEVICE_CFG.PCIeMode[3] to 1x8 (default 2x4)"},
{0x08061c, "set DEVICE_CFG.SystimeClockSource to IEEE1588_REFCLK (default PCIE_REFCLK)"},
{0x080010, "set DEVICE_CFG.PCIeEnable[0..8] to enabled"},
{0x083958, "set SBUS_PCIE_COMMAND.Op to READ [0x21]"},
{0x083970, "set SBUS_PCIE_COMMAND.Op to WRITE [0x22]"},
};
std::unordered_map<uint32_t, std::string> registerRename{
{(uint32_t) KnownRegisters::MGMT_SCRATCH_0, "custom_RETURN_VALUE"},
{(uint32_t) KnownRegisters::MGMT_SCRATCH_1, "custom_RETURN_TO"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0, "api_SPI_LOCK_STATE"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 1, "api_PCIE_SBUS_LOCK_STATE"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 2, "api_SOFT_RESET_LOCK_STATE"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 3, "api_RECOVERY_STATUS_VECTOR"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 10, "api_PEP_MAC_BASE"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 100, "api_CUSTOM_MAC_BASE"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x141, "custom_PEP_CONFIG_serial0"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x142, "custom_PEP_CONFIG_serial1"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x143, "custom_PEP_CONFIG_mgmtPep"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x144, "custom_PEP_CONFIG_vendor_device"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x145, "custom_PEP_CONFIG_subVendor_subDevice"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x145, "custom_PEP_CONFIG_gen"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x13c, "custom_PEP_CONFIG_numberOfLanes"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x17f, "custom_PEP_CONFIG_ASPMEnable"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x139, "custom_PEP_ADDR_OFFSET"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x154, "custom_PEP_NUMBER"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x12e, "param_SBUS_PCIE_REQUEST_-_SBUS_PCIE_RESPONSE"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x12f, "param_SBUS_PCIE_COMMAND_doWrite"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x130, "param_SBUS_PCIE_COMMAND.DeviceAddress"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x131, "param_SBUS_PCIE_COMMAND.Register"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x132, "custom_param_RETURN_TO_SUCCESS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x133, "custom_param_RETURN_TO_FAILURE"},
/**
* api_BSM_STATUS: Step[0-7]
*
* Step 0x0D/0x0F: core = (bsmStatus >> 20 ) & 0xFFF;
* Step 0x0E: Master version ((bsmStatus >> 24) & 0x1), Master CRC ((bsmStatus >> 20) & 0x1), Serdes version ((bsmStatus >> 24) & 0x2), Serdes CRC ((bsmStatus >> 20) & 0x2)
* Step 0x11: host = (bsmStatus >> 16 ) & 0xF;
*/
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x190, "api_BSM_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x191, "api_EEPROM_IMAGE_VERSION"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x192, "api_MASTER_FW_VERSION"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x193, "api_SERDES_FW_VERSION"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x194, "api_SERDES_STATUS_1"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x195, "api_SERDES_STATUS_2"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x196, "api_SERDES_STATUS_3"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x197, "api_SERDES_STATUS_4"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x198, "api_PCIE_MASTER_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x199, "api_PCIE_SERDES_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1ae, "api_DE_COLD_RESET_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1af, "api_SBUS_RESET_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1b0, "api_MEMORY_REPAIR_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1b1, "api_MEMORY_INIT_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1b2, "api_PCIE_PCS_DIS_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1b3, "api_PCIE_MASTER_FW_DL_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1b4, "api_PCIE_FW_CHECK_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1b5, "api_PCIE_SERDES_FW_DL_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1b6, "api_PCIE_SERDES_INIT_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1b7, "api_PCIE_PCS_EN_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1b8, "api_PCIE_DE_WARM_RESET_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1b9, "api_PCIE_ISR_STATUS_0"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1ba, "api_PCIE_ISR_STATUS_1"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1bb, "api_PCIE_ISR_STATUS_2"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1bc, "api_PCIE_ISR_STATUS_3"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1bd, "api_PCIE_ISR_STATUS_4"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1be, "api_PCIE_ISR_STATUS_5"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1bf, "api_PCIE_ISR_STATUS_6"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1c0, "api_PCIE_ISR_STATUS_7"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1c1, "api_PCIE_ISR_STATUS_8"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1c2, "api_SERDES_OOR_STATUS_PASS_1"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1c3, "api_SERDES_OOR_STATUS_PASS_2"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1c4, "api_SW_LOCK_ERR_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1c5, "api_PCIE_EN_REFCLK_STATUS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1c6, "api_RE_RESET_MASK_STATUS_1"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1c7, "api_RE_RESET_MASK_STATUS_2"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x1c8, "api_RE_RESET_ERR_STATUS"},
};
for (auto &e : knownNames) {
ctx.addMapping(e.first, e.second);
}
for (auto &c : comments) {
ctx.addComment(c.first, c.second);
}
for(uint32_t i = 10; i < 200; ++i){
if(registerRename.find((uint32_t) KnownRegisters::BSM_SCRATCH_START + i) == registerRename.end()){
std::stringstream s;
s << "api_MASK_BSM_CONFIG_" << std::dec << i;
registerRename[(uint32_t) KnownRegisters::BSM_SCRATCH_START + i] = s.str();
}
}
for(uint32_t i = 400; i < 410; ++i){
if(registerRename.find((uint32_t) KnownRegisters::BSM_SCRATCH_START + i) == registerRename.end()){
std::stringstream s;
s << "api_MASK_BSM_INIT_STATUS_" << std::dec << i;
registerRename[(uint32_t) KnownRegisters::BSM_SCRATCH_START + i] = s.str();
}
}
for(uint32_t i = 430; i < 441; ++i){
if(registerRename.find((uint32_t) KnownRegisters::BSM_SCRATCH_START + i) == registerRename.end()){
std::stringstream s;
s << "api_MASK_BSM_INIT_STATUS_ARCHIVE_" << std::dec << i;
registerRename[(uint32_t) KnownRegisters::BSM_SCRATCH_START + i] = s.str();
}
}
for(uint32_t i = 450; i < 452; ++i){
if(registerRename.find((uint32_t) KnownRegisters::BSM_SCRATCH_START + i) == registerRename.end()){
std::stringstream s;
s << "api_MASK_BSM_INIT_OOR_" << std::dec << i;
registerRename[(uint32_t) KnownRegisters::BSM_SCRATCH_START + i] = s.str();
}
}
for (auto &r : registerRename) {
ctx.addRegister(r.first, r.second);
}
ctx.analyze();
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')
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) {
std::cout << "\n\n";
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 << ": ";
op << std::hex << std::setw(6) << 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];
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 {
@ -80,12 +337,17 @@ 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::cout << "\n\n================ " << 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";
if (!ctx.getLabel(instruction->getAddress(), false).empty()) {
std::cout << "\n\n; ================ FUNCTION " << ctx.getLabel(instruction->getAddress())
<< " ================\n";
}
std::cout << ctx.getInstructionString(*instruction);
prevAddress = instruction->getEndAddress();
}
}
@ -175,7 +437,7 @@ patchImage(const std::string &originalImage, const std::string &settingsFile, co
// (BSM_ARGS = BSM_SCRATCH[0x149])
// 0x9110 LOAD 1 = 0x1 ???? do pcie init? IF 0: JUMP 0x081b78: OTHERWISE BIG BLOCK INIT?
// 0x9120 LOAD 1 = 0x0 ???? IF 0: SOFT_RESET.EPLReset = 0, SOFT_RESET.SwitchReset = 0 (RESET) ELSE: JUMP 0x080464
// 0x9120 LOAD 1 = 0x0 api.platform.config.switch.0.bootCfg.skipPcieInitialization
//
// ==0x9130 LOAD 9 api.platform.config.switch.0.bootCfg.pep.0.numberOfLanes
// 0x9160 LOAD 9 0, 4, 0, 4 ... ???? BSM_SCRATCH[0x13d]
@ -183,6 +445,7 @@ patchImage(const std::string &originalImage, const std::string &settingsFile, co
// 0x91c0 LOAD 9 ???? BSM_SCRATCH[0x13f] IF 0: JUMP 0x084da0 ELSE: PCIE_CTRL.RxLaneflipEn = 1
// ==0x91f0 LOAD 9 bar4Allowed + api.platform.config.switch.0.bootCfg.mgmtPep
// 0x9220 LOAD 1 = 0 EEPROM Major version (0x0222, 02.22 < first 0)
// ==0x9230 LOAD 9 vendor/device
// ==0x9260 LOAD 9 subVendor/subDevice
@ -193,7 +456,7 @@ patchImage(const std::string &originalImage, const std::string &settingsFile, co
// 0x9350 LOAD 9 ???? BSM_SCRATCH[0x17e], (val & 0x000000ff) something PCIe value?
// ==0x9380 LOAD 9 api.platform.config.switch.0.bootCfg.pep.0.ASPMEnable BSM_SCRATCH[0x17f] IF NOT 0: JUMP ELSE SET PCIE_CFG_PCIE_LINK_CAP.ActiveStateLinkPMSupport = 0
//
// 0x93b0 LOAD 1 = 0x00 ???? IF 0: JUMP 0x080d38 ELSE WRITE BSM_SCRATCH[0x1b0] = 0x41000c ???? DEAD code?
// 0x93b0 LOAD 1 = 0x00 api.platform.config.switch.0.bootCfg.skipMemRepair
// 0x93c0 LOAD 1 = 0x492550f0 PCIE_CLK_CTRL |= (value & 0xfffff0f0)
// 0x93cc LOAD 1 = 0x0000000f PCIE_CLK_CTRL_2 = value & 0xf
// 0x93d8 LOAD 1 = 0x00000064 PCIE_WARM_RESET_DELAY = value
@ -254,7 +517,7 @@ patchImage(const std::string &originalImage, const std::string &settingsFile, co
if (entry.type == Configuration::ConfigurationNode::Type::ValueText &&
!entry.value.empty()) {
auto value = entry.getEUI64ToInteger();
if(value.first == 0xFFFFFFFF && value.second == 0xFFFFFFFF){
if (value.first == 0xFFFFFFFF && value.second == 0xFFFFFFFF) {
value.first &= 0xFF000100 | pepOffset;
value.second &= 0x000000FF;
}
@ -280,7 +543,7 @@ patchImage(const std::string &originalImage, const std::string &settingsFile, co
if (entry.type == Configuration::ConfigurationNode::Type::ValueText &&
!entry.value.empty()) {
auto value = entry.getEUI64ToInteger();
if(value.first == 0xFFFFFFFF && value.second == 0xFFFFFFFF){
if (value.first == 0xFFFFFFFF && value.second == 0xFFFFFFFF) {
value.first &= 0xFF000100 | customMacOffset;
value.second &= 0x000000FF;
}