add zlib support (currently limited to altera spiOverJtag)

This commit is contained in:
Gwenhael Goavec-Merou 2021-11-25 08:11:50 +01:00
parent 70e9671b3a
commit 7a19f94f19
6 changed files with 131 additions and 8 deletions

View File

@ -34,7 +34,8 @@ jobs:
libhidapi-dev \
libudev-dev \
pkg-config \
tree
tree \
zlib1g-dev
- name: '🚧 Build tarball'
run: |
@ -86,7 +87,8 @@ jobs:
sudo apt install -y \
libftdi1-2 \
libhidapi-hidraw0 \
udev
udev \
zlib1g
- name: '📥 Download artifact: package'
uses: actions/download-artifact@v2

View File

@ -37,6 +37,7 @@ if(USE_PKGCONFIG)
pkg_check_modules(LIBFTDI REQUIRED libftdi1)
pkg_check_modules(LIBUSB REQUIRED libusb-1.0)
pkg_check_modules(HIDAPI hidapi-hidraw)
pkg_check_modules(ZLIB zlib)
# if hidraw not found try with libusb
if(NOT HIDAPI_FOUND)
pkg_check_modules(HIDAPI hidapi-libusb)
@ -198,6 +199,13 @@ else()
endif()
endif(ENABLE_CMSISDAP)
if (ZLIB_FOUND)
include_directories(${ZLIB_INCLUDE_DIRS})
target_link_libraries(openFPGALoader ${ZLIB_LIBRARIES})
add_definitions(-DHAS_ZLIB=1)
else()
message("zlib library not found: can't flash intel/altera devices")
endif()
endif()
if (LINK_CMAKE_THREADS)
@ -205,7 +213,6 @@ if (LINK_CMAKE_THREADS)
target_link_libraries(openFPGALoader Threads::Threads)
endif()
# libftdi < 1.4 as no usb_addr
# libftdi >= 1.5 as purge_buffer obsolete
string(REPLACE "." ";" VERSION_LIST ${LIBFTDI_VERSION})
@ -218,9 +225,11 @@ add_definitions(-DFTDI_VERSION=${FTDI_VAL})
install(TARGETS openFPGALoader DESTINATION bin)
file(GLOB BITS_FILES spiOverJtag/spiOverJtag_*.bit)
file(GLOB RBF_FILES spiOverJtag/spiOverJtag_*.rbf)
file(GLOB GZ_FILES spiOverJtag/spiOverJtag_*.rbf.gz)
install(FILES
test_sfl.svf
${BITS_FILES}
${RBF_FILES}
${GZ_FILES}
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/openFPGALoader
)

View File

@ -7,7 +7,10 @@ pkgdesc="openFPGALoader: universal utility for programming FPGA (mingw-w64)"
arch=('any')
url="https://github.com/trabucayre/openFPGALoader"
license=('Apache-2.0')
depends=("${MINGW_PACKAGE_PREFIX}-libftdi")
depends=(
"${MINGW_PACKAGE_PREFIX}-libftdi"
"${MINGW_PACKAGE_PREFIX}-zlib"
)
makedepends=(
"${MINGW_PACKAGE_PREFIX}-gcc"
"${MINGW_PACKAGE_PREFIX}-cmake"

View File

@ -156,7 +156,11 @@ bool Altera::load_bridge()
// DATA_DIR is defined at compile time.
std::string bitname = DATA_DIR "/openFPGALoader/spiOverJtag_";
#ifdef HAS_ZLIB
bitname += _device_package + ".rbf.gz";
#else
bitname += _device_package + ".rbf";
#endif
std::cout << "use: " << bitname << std::endl;

View File

@ -10,6 +10,10 @@
#include <strings.h>
#include <unistd.h>
#ifdef HAS_ZLIB
#include <zlib.h>
#endif
#include "display.hpp"
#include "configBitstreamParser.hpp"
@ -23,21 +27,49 @@ ConfigBitstreamParser::ConfigBitstreamParser(const string &filename, int mode,
{
(void) mode;
if (!filename.empty()) {
uint32_t offset = filename.find_last_of(".");
FILE *_fd = fopen(filename.c_str(), "rb");
if (!_fd)
throw std::runtime_error("Error: fail to open " + _filename);
if (!_fd) {
printf("1\n");
/* if file not found it's maybe a gz -> try without gz */
if (offset != string::npos) {
printf("2\n");
_filename = filename.substr(0, offset);
printf("%s\n", _filename.c_str());
_fd = fopen(_filename.c_str(), "rb");
}
/* test again */
if (!_fd)
throw std::runtime_error("Error: fail to open " + filename);
}
fseek(_fd, 0, SEEK_END);
_file_size = ftell(_fd);
fseek(_fd, 0, SEEK_SET);
_raw_data.resize(_file_size);
_bit_data.reserve(_file_size);
int ret = fread((char *)&_raw_data[0], sizeof(char), _file_size, _fd);
fclose(_fd);
if (ret != _file_size)
throw std::runtime_error("Error: fail to read " + _filename);
fclose(_fd);
if (offset != string::npos) {
string extension = _filename.substr(_filename.find_last_of(".") +1);
if (extension == "gz" || extension == "gzip") {
string tmp;
tmp.reserve(_file_size);
if (!decompress_bitstream(_raw_data, &tmp))
throw std::runtime_error("Error: decompress failed");
_raw_data.clear();
_raw_data.append(std::move(tmp));
_file_size = _raw_data.size();
}
}
_bit_data.reserve(_file_size);
} else if (!isatty(fileno(stdin))) {
_file_size = 0;
string tmp;
@ -119,3 +151,66 @@ uint8_t ConfigBitstreamParser::reverseByte(uint8_t src)
return revertByteArr[src];
#endif
}
bool ConfigBitstreamParser::decompress_bitstream(string source, string *dest)
{
#ifndef HAS_ZLIB
(void)source;
(void)dest;
printError("openFPGALoader is build without zlib support\n"
"can't uncompress file\n");
return false;
#else
#define CHUNK 16384
int ret;
unsigned have;
z_stream strm;
unsigned char *in = (unsigned char *)&source[0];
unsigned char out[CHUNK];
/* allocate inflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit2(&strm, 15+16);
if (ret != Z_OK)
return ret;
uint32_t pos = source.size();
uint32_t xfer = CHUNK;
/* decompress until deflate stream ends or end of file */
do {
/* if buffer has a size < CHUNK */
if (pos < CHUNK)
xfer = pos;
strm.next_in = in; // chunk to uncompress
strm.avail_in = xfer; // chunk size
/* run inflate() on input until output buffer not full */
do {
strm.avail_out = CHUNK; // specify buffer size
strm.next_out = out; // buffer
ret = inflate(&strm, Z_BLOCK);
if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR
|| ret == Z_MEM_ERROR) {
(void)inflateEnd(&strm);
return false;
}
have = CHUNK - strm.avail_out; // compute data size
// after uncompress
dest->append((const char*)out, have); // store
} while (strm.avail_in != 0);
in += xfer; // update input buffer position
pos -= xfer; // update len to decompress
/* done when inflate() says it's done */
} while (ret != Z_STREAM_END);
/* clean up and return */
(void)inflateEnd(&strm);
return ret == Z_STREAM_END;
#endif
}

View File

@ -47,6 +47,16 @@ class ConfigBitstreamParser {
static uint8_t reverseByte(uint8_t src);
private:
/**
* \brief decompress bitstream in gzip format
* \param[in] source: raw compressed data
* \param[out] dest: raw uncompressed data
* \return false if openFPGALoader is build without zlib or
* if uncompress fails
*/
bool decompress_bitstream(std::string source, std::string *dest);
protected:
std::string _filename;
int _bit_length;