int LatticeBitParser::parseHeader()
{
int currPos = 0;
if (_raw_data.empty()) {
printError("LatticeBitParser: empty bitstream");
return EXIT_FAILURE;
}
const uint32_t file_size = static_cast<uint32_t>(_raw_data.size());
/* check header signature */
/* radiant .bit start with LSCC */
if (_raw_data[0] == 'L') {
if (file_size < 4) {
printError("LatticeBitParser: bitstream too small");
return EXIT_FAILURE;
}
if (_raw_data.compare(0, 4, "LSCC") != 0) {
printf("Wrong File %s\n", _raw_data.substr(0, 4).c_str());
return EXIT_FAILURE;
}
currPos += 4;
}
/* Check if bitstream size may store at least 0xff00 + another 0xff */
if (file_size <= currPos + 3) {
printError("LatticeBitParser: bitstream too small");
return EXIT_FAILURE;
}
/* bit file comment area start with 0xff00 */
if ((uint8_t)_raw_data[currPos] != 0xff ||
(uint8_t)_raw_data[currPos + 1] != 0x00) {
printf("Wrong File %02x%02x\n", (uint8_t) _raw_data[currPos],
(uint8_t)_raw_data[currPos + 1]);
return EXIT_FAILURE;
}
currPos += 2;
_endHeader = _raw_data.find(0xff, currPos);
if (_endHeader == std::string::npos) {
printError("Error: preamble not found\n");
return EXIT_FAILURE;
}
/* .bit for MACHXO3D seems to have more 0xff before preamble key */
size_t pos = _raw_data.find(0xb3, _endHeader);
if (pos == std::string::npos) {
printError("Preamble key not found");
return EXIT_FAILURE;
}
/* preamble must have at least 3 x 0xff + enc_key byte before 0xb3 */
if (pos < _endHeader + 4) {
printError("LatticeBitParser: wrong preamble size");
return EXIT_FAILURE;
}
//0xbe is the key for encrypted bitstreams in Nexus fpgas
const uint8_t enc_key = static_cast<uint8_t>(_raw_data[pos - 1]);
if (enc_key != 0xbd && enc_key != 0xbf && enc_key != 0xbe) {
printError("Wrong preamble key");
return EXIT_FAILURE;
}
_endHeader = pos - 4; // align to 3 Dummy Bytes + preamble (ie. Header start offset).
if (currPos >= _endHeader) {
printError("LatticeBitParser: no header");
return EXIT_FAILURE;
}
/* parse header */
std::string_view lineStream(_raw_data.data() + currPos, _endHeader - currPos);
while (!lineStream.empty()) {
const size_t null_pos = lineStream.find('\0');
const std::string_view buff = lineStream.substr(0, null_pos);
pos = buff.find(':');
if (pos != std::string_view::npos) {
const std::string_view key = buff.substr(0, pos);
const std::string_view val = buff.substr(pos + 1);
const size_t startPos = val.find_first_not_of(' ');
if (startPos != std::string_view::npos) {
const size_t endPos = val.find_last_not_of(' ');
_hdr.insert_or_assign(std::string(key),
std::string(val.substr(startPos, endPos - startPos + 1)));
}
}
if (null_pos == std::string_view::npos)
break;
lineStream = lineStream.substr(null_pos + 1);
}
return EXIT_SUCCESS;
}