As answered in Make package registry searchable in the CLI or GUI · Issue #3836 · platformio/platformio-core · GitHub. Usually with API requests like https://api.registry.platformio.org/v3/packages/platformio/tool/toolchain-gccarmnoneeabi
, replacing toolchain-gccarmnoneeabi
with the needed tool name. So in your case https://api.registry.platformio.org/v3/packages/platformio/tool/tool-dfuutil.
A general explanation of PlatformIO packages is at the official docs and here.
You can compile it yourself as a fallback, then the devs can upload your package. The general gist is:
- Find out where the sources for a package live
- Compile it (install depenendencies,
make
andmake install ...
) - package it
3.1. writepackage.json
3.2. usepio package pack
to generate the archive file
Let’s go through the steps together. We know tool-dfuutil
is missing for the linux_aarch64 (ARM64) system. For a Linux system it’s always a good idea to look at the package for other Linux systems for the same version (~1.9.190708
is a SemVer expression matching the latest “1.9.x” version). Using the API link above, we can see
- the package name “tool-dfuutil-linux_x86_64-1.9.200310.tar.gz” with a download link of https://dl.registry.platformio.org/download/platformio/tool/tool-dfuutil/1.9.200310/tool-dfuutil-linux_x86_64-1.9.200310.tar.gz
- but can actually also see the 32-bit ARM versions (arvm6l, armv7l, armv8l) under “tool-dfuutil-linux_armv6l-1.9.190708.tar.gz” with download link https://dl.registry.platformio.org/download/platformio/tool/tool-dfuutil/1.9.190708/tool-dfuutil-linux_armv6l-1.9.190708.tar.gz, which is even closer to our ARM64 architecture, so we take that.
- we also see that there is no package of whatever version for
linux_aarch64
. So we are forced to generate the package ourselves instead of specifying a different existing package version that may or may not work, since there is no other existing version.
So we grab that and extract that to have a look. We see…
etc.
So, where do we find where can compile that ourselves? Look at the contained package.json
. It says
{
"name": "tool-dfuutil",
"version": "1.9.190708",
"description": "Device Firmware Upgrade Utilities",
"keywords": [
"tools",
"uploader"
],
"homepage": "http://dfu-util.sourceforge.net/",
"license": "GPL-2.0-or-later",
"system": [
"linux_armv6l",
"linux_armv7l",
"linux_armv8l"
],
"repository": {
"type": "git",
"url": "https://sourceforge.net/p/dfu-util/dfu-util/ci/master/tree/"
}
}
So there it clearly shows the repo for the package being dfu-util / Code / [7e1fc9].
So, we go there and take a look at the available version. PIO says, through the version encoding “1.9.190708”, that the package has version “0.0.9” (from SemVer “9”), Datecode 190708= 2019-July-8th. We want to get something close to that. We can also execute the original Linux (or Windows) binary and ask it for its version
C:\Users\Max\.platformio\packages\tool-dfuutil\bin>dfu-util --version
dfu-util 0.9
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2020 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
So then, one might be compelled to use the repo with their tag “v0.9” (dfu-util / Code / [1d2bec]) to get version 0.9, the last source change from there being in 2016. I however vaguely remember some people having problems with this old DFU-util version in other platforms. Since it’s however that’s what PlatformIO is using, we’ll go with that. Feel free to compile from a newer dfu-util
if you like.
So, on a system capable of compiling for AArch64 (aka your Raspberry Pi), we can start trying to copile dfu-util
. The repository website already says we can clone the repo by doing
git clone https://git.code.sf.net/p/dfu-util/dfu-util dfu-util-dfu-util
(which will clone it in a folder named dfu-util-dfu-util
in an author-projectname style).
After doing a sudo apt install git
to get git
as an available command in the first place, I execute the above command on my Pi (running on a 32-bit Raspbian system, just for demonstration…), and I get the dfu-util-dfu-util
folder.
We still have to checkout the correct tag from the repo. So I
cd dfu-util-dfu-util
git checkout v0.9
which says HEAD is now at 1d2bec5 Release 0.9
. Great.
How do we compile? We follow their instructions.
You will however notice that we’re missing some dependencies for even the first step, doing
pi@raspberrypi:~/dfu-util-dfu-util $ ./autogen.sh
./autogen.sh: 2: ./autogen.sh: autoreconf: not found
since I’m not having any build tools installed. A quick googling shows the missing package can be installed via sudo apt install autoconf
. I also install the build-essentials
package to make sure I have a basic compiler. After that
pi@raspberrypi:~/dfu-util-dfu-util $ ./autogen.sh
autoreconf: Entering directory `.'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal
autoreconf: configure.ac: tracing
autoreconf: configure.ac: creating directory m4
autoreconf: configure.ac: not using Libtool
autoreconf: running: /usr/bin/autoconf
autoreconf: running: /usr/bin/autoheader
autoreconf: running: automake --add-missing --copy --no-force
configure.ac:14: installing 'm4/compile'
configure.ac:7: installing 'm4/install-sh'
configure.ac:7: installing 'm4/missing'
src/Makefile.am: installing 'm4/depcomp'
autoreconf: Leaving directory `.'
the output looks better. The next step in their INSTALL
guide says to
pi@raspberrypi:~/dfu-util-dfu-util $ ./configure
autoreconf: Entering directory `.'
[...]
checking pkg-config is at least version 0.9.0... yes
checking for USB... no
configure: error: *** Required libusb-1.0 >= 1.0.0 not installed ***
which leads us to the next missing dependency, libusb-1.0. After doing a quick search via sudo apt search libusb-1.0
we get that we need the libusb-1.0-0-dev
(development package) to compile stuff for LibUSB-1.0. So, one sudo apt install libusb-1.0-0-dev
later and rerunning the command…
pi@raspberrypi:~/dfu-util-dfu-util $ ./configure
[...]
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating doc/Makefile
config.status: creating config.h
config.status: executing depfiles commands
And that has now created the Makefiles successfully. So, we follow next command (make
) but take the liberty to add -j4
to it, to make compilation multi-threaded on 4 cores.
It should quickly end in
CCLD dfu-util
CCLD dfu-suffix
CCLD dfu-prefix
make[2]: Leaving directory '/home/pi/dfu-util-dfu-util/src'
Making all in doc
make[2]: Entering directory '/home/pi/dfu-util-dfu-util/doc'
make[2]: Nothing to be done for 'all'.
make[2]: Leaving directory '/home/pi/dfu-util-dfu-util/doc'
make[2]: Entering directory '/home/pi/dfu-util-dfu-util'
make[2]: Leaving directory '/home/pi/dfu-util-dfu-util'
make[1]: Leaving directory '/home/pi/dfu-util-dfu-util'
showing that the needed binaries have been created in some build output folders.
Now we want to install the package to a specific folder so that we get the same nice bin/
, lib/
, share/
folder structure we saw in the reference Linux package, we don’t want to hand-pick the needed binaries and libraries.
One could now do the next step in the guide, (sudo) make install
, but that will install the system package-wide. We don’t want that, we want to just copy the package to a specific folder. So we use the DESTDIR
option for make
to specify a destination directory, a new folder which we create.
pi@raspberrypi:~/dfu-util-dfu-util $ mkdir installed
pi@raspberrypi:~/dfu-util-dfu-util $ make DESTDIR=$(pwd)/installed install
[..]
make[1]: Leaving directory '/home/pi/dfu-util-dfu-util'
If I look into the newly cleared installed
directory with the tree
command…
pi@raspberrypi:~/dfu-util-dfu-util $ tree installed/
installed/
└── usr
└── local
├── bin
│ ├── dfu-prefix
│ ├── dfu-suffix
│ └── dfu-util
└── share
└── man
└── man1
└── dfu-util.1
We get almost the needed folder structure. It did not generate the lib/
folder with
in it that the reference package had – and to be honest, I don’t think that’s even necessary. But for consistency, we will copy in those files too.
By going into the installed/usr/local/bin
directory and using the loader (ldd
) to show us where all the loaded libraries come from, we see
pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local/bin $ ldd dfu-util
linux-vdso.so.1 (0x7eff7000)
/usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so => /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so (0x76ec1000)
libusb-1.0.so.0 => /lib/arm-linux-gnueabihf/libusb-1.0.so.0 (0x76e9c000)
..
where we need to copy the file from. So we create the lib/
directory, copy in that file, which is a symbolic link to
$ ls -l /lib/arm-linux-gnueabihf/libusb-1.0.so.0
lrwxrwxrwx 1 root root 19 May 5 2018 /lib/arm-linux-gnueabihf/libusb-1.0.so.0 -> libusb-1.0.so.0.1.0
and also recreate the symbolic link from libusb-1.0.so.0
to libusb-1.0.so.0.1.0
.
pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local $ mkdir lib
pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local $ cd lib
pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local/lib $ cp /lib/arm-linux-gnueabihf/libusb-1.0.so.0.1.0 .
pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local/lib $ ln -s libusb-1.0.so.0.1.0 libusb-1.0.so.0
pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local/lib $ ls -la
total 92
drwxr-xr-x 2 pi pi 4096 Oct 20 13:11 .
drwxr-xr-x 5 pi pi 4096 Oct 20 13:10 ..
lrwxrwxrwx 1 pi pi 19 Oct 20 13:11 libusb-1.0.so.0 -> libusb-1.0.so.0.1.0
-rw-r--r-- 1 pi pi 83828 Oct 20 13:10 libusb-1.0.so.0.1.0
And while we’re there it’s also good to do a quick sanity check that the binary is actually working…
pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local/bin $ ./dfu-util --version
dfu-util 0.9
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
which it does, and it outputs the correct version as before.
Now we have the nice
pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local $ tree
.
├── bin
│ ├── dfu-prefix
│ ├── dfu-suffix
│ └── dfu-util
├── lib
│ ├── libusb-1.0.so.0 -> libusb-1.0.so.0.1.0
│ └── libusb-1.0.so.0.1.0
└── share
└── man
└── man1
└── dfu-util.1
package folder. It’s missing however the package.json
in the root of the package.
So to fix that, we copy in the original package.json
from the reference Linux ARMv6L package then adjust the systems
array to declare compatibility for the needed linux_aarch64
architecture (that info comes from the error message), and we also update the version
field to reflect the build date. So end up having this package.json
{
"name": "tool-dfuutil",
"version": "1.9.211020",
"description": "Device Firmware Upgrade Utilities",
"keywords": [
"tools",
"uploader"
],
"homepage": "http://dfu-util.sourceforge.net/",
"license": "GPL-2.0-or-later",
"system": [
"linux_aarch64"
],
"repository": {
"type": "git",
"url": "https://sourceforge.net/p/dfu-util/dfu-util/ci/master/tree/"
}
}
saved in ~/dfu-util-dfu-util/installed/usr/local
. (I just nano package.json
at the appropriate place and copy-paste in the file contents.)
We can now finally create the PlatformIO package using
pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local $ pio package pack
Wrote a tarball to "/home/pi/dfu-util-dfu-util/installed/usr/local/tool-dfuutil-linux_aarch64-1.9.211020.tar.gz"
And that is the needed tarball. For convenience I also copy it my home folder
pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local $ cp tool-dfuutil-linux_aarch64-1.9.211020.tar.gz ~/.
So if I now have a PlatformIO project, I can reference the package using platform_packages
with a file://
URI and the absolute path to the file (/home/pi/tool-dfuutil-linux_aarch64-1.9.211020.tar.gz
in my case). Add
platform_packages =
tool-dfuutil@file:///home/pi/tool-dfuutil-linux_aarch64-1.9.211020.tar.gz
to the platformio.ini
of the project to use the generated package and try uploading again.
Let me know if that gives you a working DFU-UTIL package for AArch64, and please share the generated tarball