How to Compile usbliter8 Firmware from Source on macOS

Aug 14, 2026 • Reverse Engineering • Insidebinary Team
Table of contents

In a previous write-up we looked at the hardware side of usbliter8. A natural follow-up question is whether you can build the .uf2 firmware yourself instead of relying on a prebuilt binary.

The answer is yes. This guide walks through setting up the Raspberry Pi Pico cross-compilation toolchain on macOS and compiling usbliter8.uf2 for the Waveshare RP2350-USB-A board.

Why build it yourself?

  1. Transparency and trust: for security research, compiling low-level firmware from source is often the best way to understand what will run on the device.
  2. Hardware customization: if you are using a custom RP2350 board instead of the Waveshare reference board, you may need to adjust pin definitions in the source.
  3. Reproducibility: rebuilding the firmware yourself makes it easier to verify the toolchain, patches, and final artifacts.

Step 1: Install the cross-compiler toolchain

The RP2350 targets ARM Cortex-M33 or RISC-V style embedded workflows, so a normal macOS compiler toolchain is not enough. Install the required build tools and ARM cross-compiler first:

# Install CMake, Ninja, and the ARM GCC toolchain
brew install cmake ninja
brew install --cask gcc-arm-embedded

Step 2: Fetch the Raspberry Pi Pico SDK

To compile for RP2350, you need the official Pico SDK. It provides the low-level libraries used to control GPIO and other peripherals.

Clone it into a clean working directory:

cd ~/projects
git clone --recursive https://github.com/raspberrypi/pico-sdk.git
 
export PICO_SDK_PATH=~/projects/pico-sdk

It is a good idea to add this environment variable to your shell profile so you do not have to re-export it every time:

echo 'export PICO_SDK_PATH=~/projects/pico-sdk' >> ~/.zshrc

Step 3: Obtain the usbliter8 source tree

Assuming you already have a copy of the usbliter8 source archive from a mirror or another trusted source, move into the extracted source directory:

cd ~/projects/fireware/src-usbliter8/prdgmshift-usbliter8-d6eca4f

Some of the more interesting files in this tree are:

  • exploit.c: the timing and payload delivery logic
  • usb.c: the low-level USB PIO handling
  • boards/: per-board pin definitions and configuration

Step 4: Configure and build with CMake

Next, generate a build for the Waveshare RP2350-USB-A target:

mkdir build
cd build
 
cmake .. -DPICO_BOARD=waveshare_rp2350_usb_a
make -j8

Troubleshooting: undefined reference to set_ws2812

With newer Pico SDK versions, you may hit a link error during the final stage:

/led.c:27:(.text._led_timer_cb+0xc): undefined reference to `set_ws2812'
collect2: error: ld returned 1 exit status

Why this happens

The original led.c relies on set_ws2812, which used to be externally reachable in older Pico SDK revisions. In newer SDK versions, that function is no longer linkable the same way, so the linker cannot resolve it.

A practical fix

The LED feedback is not part of the core USB logic, so the simplest workaround is to stub the function out.

Open led.c and replace the external declaration with a local stub:

// Delete or comment out this line:
// extern void set_ws2812(uint32_t value);
 
// Replace it with:
void set_ws2812(uint32_t value) {
    // Ignore LED color setting to bypass the linker error.
}

Then run the build again:

make -j8

If everything is wired up correctly, you should see:

[100%] Built target usbliter8

Step 5: Locate the generated UF2

After a successful build, the build/ directory should contain:

usbliter8.uf2

This is the firmware image you can flash onto the supported RP2350 board.

Pro tip: build all supported variants

The source tree also includes a convenience script named build_release.sh. Running it builds multiple supported board targets and collects the results into artifacts/:

./build_release.sh

That is useful if you want binaries for boards such as:

  • pico2
  • pimoroni_tiny2350
  • waveshare_rp2350_usb_a

Conclusion

Building the firmware yourself gives you a much clearer view of the full path from source code to flashable .uf2 image. It also makes it easier to patch board definitions, work around SDK regressions, and keep your toolchain reproducible.

If you are working with RP2350-based jailbreak or USB research hardware, that extra control is often worth the setup time.

jailbreak
usbliter8
firmware
rp2350
macos