From ebf2f6fd80bc1c0beb2ef1af211ab7ff3e9b7bae Mon Sep 17 00:00:00 2001 From: zhangyh <717572325@qq.com> Date: Fri, 12 Dec 2025 02:55:31 +0000 Subject: [PATCH] efinix: Add header parsing and flash programming validation Parse bitstream header to extract Mode, Width and Device fields. Add validation for flash programming: - Check device matches --fpga-part parameter - Reject passive mode (only active mode supported for flash) This prevents flashing incorrect bitstreams that would fail to boot. --- src/efinix.cpp | 24 +++++++++++++++++++++ src/efinixHexParser.cpp | 46 +++++++++++++++++++++++++++++++++++++++++ src/efinixHexParser.hpp | 3 +++ 3 files changed, 73 insertions(+) diff --git a/src/efinix.cpp b/src/efinix.cpp index 5002531..669133b 100644 --- a/src/efinix.cpp +++ b/src/efinix.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -205,6 +206,29 @@ void Efinix::program(unsigned int offset, bool unprotect_flash) if (_verbose) bit->displayHeader(); + if (_mode == FLASH_MODE) { + try { + if (!_device_package.empty()) { + std::string device = bit->getHeaderVal("device"); + std::transform(device.begin(), device.end(), device.begin(), ::tolower); + std::string target = _device_package; + std::transform(target.begin(), target.end(), target.begin(), ::tolower); + if (!device.empty() && device != target) { + delete bit; + throw std::runtime_error("device mismatch: " + device + " != " + target); + } + } + std::string mode = bit->getHeaderVal("mode"); + if (mode.find("passive") != std::string::npos) { + delete bit; + throw std::runtime_error("passive mode not supported for flash"); + } + } catch (std::runtime_error& e) { + throw; + } catch (...) { + } + } + switch (_mode) { case MEM_MODE: if (!programJTAG(data, length)) { diff --git a/src/efinixHexParser.cpp b/src/efinixHexParser.cpp index c6d4639..30d2f44 100644 --- a/src/efinixHexParser.cpp +++ b/src/efinixHexParser.cpp @@ -17,9 +17,55 @@ EfinixHexParser::EfinixHexParser(const string &filename): false) {} +int EfinixHexParser::parseHeader() +{ + string buffer; + istringstream lineStream(_raw_data); + int bytesRead = 0; + string headerText; + bool foundPaddedBits = false; + + while (std::getline(lineStream, buffer, '\n')) { + bytesRead += buffer.size() + 1; + + if (buffer != "0A") { + try { + uint8_t byte = std::stol(buffer, nullptr, 16); + headerText += (char)byte; + } catch (...) { + } + } else { + headerText += '\n'; + if (foundPaddedBits) + break; + } + + if (headerText.find("PADDED_BITS") != string::npos) + foundPaddedBits = true; + } + + size_t pos; + if ((pos = headerText.find("Mode: ")) != string::npos) { + size_t end = headerText.find('\n', pos); + _hdr["mode"] = headerText.substr(pos + 6, end - pos - 6); + } + if ((pos = headerText.find("Width: ")) != string::npos) { + size_t end = headerText.find('\n', pos); + _hdr["width"] = headerText.substr(pos + 7, end - pos - 7); + } + if ((pos = headerText.find("Device: ")) != string::npos) { + size_t end = headerText.find('\n', pos); + _hdr["device"] = headerText.substr(pos + 8, end - pos - 8); + } + + return bytesRead; +} + int EfinixHexParser::parse() { string buffer; + parseHeader(); + istringstream lineStream(_raw_data); while (std::getline(lineStream, buffer, '\n')) { diff --git a/src/efinixHexParser.hpp b/src/efinixHexParser.hpp index 6cf0f03..73af05b 100644 --- a/src/efinixHexParser.hpp +++ b/src/efinixHexParser.hpp @@ -28,6 +28,9 @@ class EfinixHexParser: public ConfigBitstreamParser { * \return EXIT_SUCCESS is file is fully read, EXIT_FAILURE otherwise */ int parse() override; + + private: + int parseHeader(); }; #endif // SRC_EFINIXHEXPARSER_HPP_