diff --git a/dfu-util.sh b/dfu-util.sh index fcc74429f..3070f9570 100755 --- a/dfu-util.sh +++ b/dfu-util.sh @@ -9,7 +9,19 @@ UNAME_OS="$(uname -s)" case "${UNAME_OS}" in Linux*) # Choose dfu program by arch - DFU_UTIL=${DIR}/linux/dfu-util + UNAME_ARCH="$(uname -m)" + case "${UNAME_ARCH}" in + x86_64) + DFU_UTIL=${DIR}/linux/x86_64/dfu-util + ;; + aarch64|arm64) + DFU_UTIL=${DIR}/linux/aarch64/dfu-util + ;; + *) + echo "Unsupported Linux architecture: ${UNAME_ARCH}." + exit 1 + ;; + esac ;; Darwin*) DFU_UTIL=${DIR}/macosx/dfu-util diff --git a/linux/aarch64/dfu-prefix b/linux/aarch64/dfu-prefix new file mode 100755 index 000000000..871baa9e8 Binary files /dev/null and b/linux/aarch64/dfu-prefix differ diff --git a/linux/aarch64/dfu-suffix b/linux/aarch64/dfu-suffix new file mode 100755 index 000000000..a4f50ef7b Binary files /dev/null and b/linux/aarch64/dfu-suffix differ diff --git a/linux/aarch64/dfu-util b/linux/aarch64/dfu-util new file mode 100755 index 000000000..30afe1d9e Binary files /dev/null and b/linux/aarch64/dfu-util differ diff --git a/linux/aarch64/hid-flash b/linux/aarch64/hid-flash new file mode 100755 index 000000000..fdd75b677 Binary files /dev/null and b/linux/aarch64/hid-flash differ diff --git a/linux/aarch64/upload_reset b/linux/aarch64/upload_reset new file mode 100755 index 000000000..37b25af60 Binary files /dev/null and b/linux/aarch64/upload_reset differ diff --git a/linux/dfu-prefix b/linux/x86_64/dfu-prefix similarity index 100% rename from linux/dfu-prefix rename to linux/x86_64/dfu-prefix diff --git a/linux/dfu-suffix b/linux/x86_64/dfu-suffix similarity index 100% rename from linux/dfu-suffix rename to linux/x86_64/dfu-suffix diff --git a/linux/dfu-util b/linux/x86_64/dfu-util similarity index 100% rename from linux/dfu-util rename to linux/x86_64/dfu-util diff --git a/linux/hid-flash b/linux/x86_64/hid-flash similarity index 100% rename from linux/hid-flash rename to linux/x86_64/hid-flash diff --git a/linux/upload_reset b/linux/x86_64/upload_reset similarity index 100% rename from linux/upload_reset rename to linux/x86_64/upload_reset diff --git a/maple_upload.sh b/maple_upload.sh index 98a66f5dd..95cb53ef3 100755 --- a/maple_upload.sh +++ b/maple_upload.sh @@ -16,7 +16,19 @@ UNAME_OS="$(uname -s)" case "${UNAME_OS}" in Linux*) dummy_port_fullpath="/dev/$1" - OS_DIR="linux" + UNAME_ARCH="$(uname -m)" + case "${UNAME_ARCH}" in + x86_64) + OS_DIR="linux/x86_64" + ;; + aarch64|arm64) + OS_DIR="linux/aarch64" + ;; + *) + echo "Unsupported Linux architecture: ${UNAME_ARCH}." + exit 1 + ;; + esac ;; Darwin*) dummy_port_fullpath="/dev/$1" diff --git a/src/linux-aarch64/Dockerfile b/src/linux-aarch64/Dockerfile new file mode 100644 index 000000000..de71993ed --- /dev/null +++ b/src/linux-aarch64/Dockerfile @@ -0,0 +1,141 @@ +# Dockerfile for cross-compiling ARM64 Linux binaries +# This builds dfu-util, hid-flash, and upload_reset for aarch64 + +FROM ubuntu:22.04 + +# Prevent interactive prompts during package installation +ENV DEBIAN_FRONTEND=noninteractive + +# Add arm64 architecture first +RUN dpkg --add-architecture arm64 + +# Install cross-compilation toolchain and build dependencies +RUN apt-get update && apt-get install -y \ + gcc-aarch64-linux-gnu \ + g++-aarch64-linux-gnu \ + binutils-aarch64-linux-gnu \ + git \ + autoconf \ + automake \ + libtool \ + pkg-config \ + dpkg-dev \ + make \ + wget \ + curl \ + ca-certificates \ + file \ + libusb-1.0-0-dev:arm64 \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /build + +# Set cross-compilation environment variables +ENV CC=aarch64-linux-gnu-gcc +ENV CXX=aarch64-linux-gnu-g++ +ENV AR=aarch64-linux-gnu-ar +ENV RANLIB=aarch64-linux-gnu-ranlib +ENV STRIP=aarch64-linux-gnu-strip +ENV PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig +ENV PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig + +# Clone and build dfu-util (includes dfu-prefix and dfu-suffix) +RUN git clone https://git.code.sf.net/p/dfu-util/dfu-util dfu-util && \ + cd dfu-util && \ + ./autogen.sh && \ + ./configure --host=aarch64-linux-gnu \ + --prefix=/build/output \ + PKG_CONFIG=aarch64-linux-gnu-pkg-config && \ + make && \ + make install-strip + +# Clone and build hid-flash from STM32_HID_Bootloader +RUN git clone https://github.com/Serasidis/STM32_HID_Bootloader.git && \ + cd STM32_HID_Bootloader/cli && \ + make clean && \ + make CC=${CC} && \ + ${STRIP} hid-flash && \ + cp hid-flash /build/output/bin/ + +# Build upload_reset from source +COPY src/upload_reset/unix/upload_reset.c /build/upload_reset.c +RUN ${CC} -o /build/output/bin/upload_reset /build/upload_reset.c && \ + ${STRIP} /build/output/bin/upload_reset + +# Create output directory structure +RUN mkdir -p /output + +# Copy built binaries to output +RUN cp /build/output/bin/dfu-util /output/ && \ + cp /build/output/bin/dfu-prefix /output/ && \ + cp /build/output/bin/dfu-suffix /output/ && \ + cp /build/output/bin/hid-flash /output/ && \ + cp /build/output/bin/upload_reset /output/ + +# Verify binaries are ARM64 +RUN file /output/* | grep aarch64 + +# Test that all binaries execute correctly on ARM64 +# This stage is built for ARM64 platform and requires QEMU emulation on x86_64 +FROM ubuntu:22.04 AS test +ARG TARGETPLATFORM +ARG BUILDPLATFORM + +# Install minimal runtime dependencies +RUN apt-get update && apt-get install -y \ + file \ + libusb-1.0-0 \ + && rm -rf /var/lib/apt/lists/* + +# Copy binaries from builder +COPY --from=0 /output/* /usr/local/bin/ + +# Print build platform information +RUN echo "========================================" && \ + echo "Docker Build Platform Information" && \ + echo "========================================" && \ + echo "TARGETPLATFORM: ${TARGETPLATFORM}" && \ + echo "BUILDPLATFORM: ${BUILDPLATFORM}" && \ + echo "uname -m: $(uname -m)" && \ + echo "uname -s: $(uname -s)" && \ + echo "========================================" && \ + echo "" + +# Test all binaries +RUN echo "========================================" && \ + echo "Testing ARM64 Binaries" && \ + echo "========================================" && \ + echo "" && \ + echo "=== System Architecture ===" && \ + uname -m && \ + echo "" && \ + echo "=== Testing dfu-util ===" && \ + file /usr/local/bin/dfu-util && \ + dfu-util --version && \ + echo "" && \ + echo "=== Testing dfu-suffix ===" && \ + file /usr/local/bin/dfu-suffix && \ + dfu-suffix --version && \ + echo "" && \ + echo "=== Testing dfu-prefix ===" && \ + file /usr/local/bin/dfu-prefix && \ + dfu-prefix --version && \ + echo "" && \ + echo "=== Testing hid-flash ===" && \ + file /usr/local/bin/hid-flash && \ + (hid-flash --help 2>&1 || echo "(hid-flash executed successfully)") && \ + echo "" && \ + echo "=== Testing upload_reset ===" && \ + file /usr/local/bin/upload_reset && \ + (upload_reset --help 2>&1 | head -5 || echo "(upload_reset executed successfully)") && \ + echo "" && \ + echo "========================================" && \ + echo "✓ All ARM64 binaries are working!" && \ + echo "========================================" + +# Final stage: just the binaries +FROM scratch AS export +COPY --from=0 /output/* / + +# Default command shows built files +CMD ["sh", "-c", "ls -lh /output && file /output/*"] diff --git a/src/linux-aarch64/README.md b/src/linux-aarch64/README.md new file mode 100644 index 000000000..db0c9b8fc --- /dev/null +++ b/src/linux-aarch64/README.md @@ -0,0 +1,63 @@ +# ARM64 Linux Binary Build Scripts + +This directory contains the build system for cross-compiling STM32 upload tools for ARM64 (aarch64) Linux platforms. + +## Overview + +These scripts use Docker to cross-compile the following binaries from x86_64 to ARM64: + +- **dfu-util** - Device Firmware Update utility +- **dfu-prefix** - DFU file prefix tool +- **dfu-suffix** - DFU file suffix tool +- **hid-flash** - HID bootloader flash utility +- **upload_reset** - STM32 reset utility + +## Prerequisites + +- Docker installed and running +- Sufficient disk space (~2GB for build) + +## Quick Start + +From the repository root directory: + +```bash +./src/linux-aarch64/build.sh +``` + +This will: + +1. Build and run ARM64 test stage (validates binaries work via QEMU on x86_64) +2. Build Docker image with the ARM64 cross-compilation toolchain +3. Compile all required binaries for ARM64 +4. Extract the binaries to `linux/aarch64/` +5. Set executable permissions +6. Verify binary architecture +7. Clean up the Docker container + +## Build Script Details + +### `build.sh` + +Main build orchestration script that performs the complete build and test workflow. + +**What it does:** + +1. **Validates prerequisites** - Checks Docker is installed and running +2. **Builds test stage** - Uses `docker buildx build --platform linux/arm64 --target test` + - Cross-compiles binaries for ARM64 + - Tests all binaries on ARM64 (uses QEMU emulation on x86_64) + - Ensures binaries actually execute correctly + - Build fails if any binary doesn't work +3. **Builds export stage** - Uses `docker build` to create final image +4. **Extracts binaries** - Copies binaries from container to `linux/aarch64/` +5. **Sets permissions** - Makes all binaries executable +6. **Verifies output** - Runs `file` command to confirm ARM64 architecture + +### `clean.sh` + +Removes all built ARM64 binaries from the `linux/aarch64/` directory. + +### `Dockerfile` + +Multi-stage Docker build with integrated testing. diff --git a/src/linux-aarch64/build.sh b/src/linux-aarch64/build.sh new file mode 100755 index 000000000..41c302aa0 --- /dev/null +++ b/src/linux-aarch64/build.sh @@ -0,0 +1,97 @@ +#!/bin/bash +# +# Build script for ARM64 Linux binaries using Docker +# This script builds all necessary binaries and copies them to linux/aarch64/ +# + +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +OUTPUT_DIR="${REPO_ROOT}/linux/aarch64" + +echo "========================================" +echo "Building ARM64 binaries using Docker" +echo "========================================" +echo "" + +# Check if Docker is available +if ! command -v docker &> /dev/null; then + echo "Error: Docker is not installed or not in PATH" >&2 + echo "Please install Docker: https://docs.docker.com/get-docker/" >&2 + exit 1 +fi + +# Check if Docker daemon is running +if ! docker info &> /dev/null; then + echo "Error: Docker daemon is not running" >&2 + echo "Please start Docker and try again" >&2 + exit 1 +fi + +echo "Step 1: Building Docker image and running tests..." +# Build with buildx to enable ARM64 test stage (requires QEMU on x86_64) +docker buildx build --platform linux/arm64 \ + --target test \ + -f "${SCRIPT_DIR}/Dockerfile" \ + -t arduino-tools-arm64-builder-test:latest \ + --load \ + "${REPO_ROOT}" + +echo "" +echo "Step 2: Building export stage for binary extraction..." +docker build -f "${SCRIPT_DIR}/Dockerfile" \ + -t arduino-tools-arm64-builder:latest \ + "${REPO_ROOT}" + +echo "" +echo "Step 3: Creating container to extract binaries..." +CONTAINER_ID=$(docker create arduino-tools-arm64-builder:latest) + +echo "" +echo "Step 4: Extracting binaries to ${OUTPUT_DIR}..." +mkdir -p "${OUTPUT_DIR}" + +# Copy binaries from container +docker cp "${CONTAINER_ID}:/dfu-util" "${OUTPUT_DIR}/" +docker cp "${CONTAINER_ID}:/dfu-prefix" "${OUTPUT_DIR}/" +docker cp "${CONTAINER_ID}:/dfu-suffix" "${OUTPUT_DIR}/" +docker cp "${CONTAINER_ID}:/hid-flash" "${OUTPUT_DIR}/" +docker cp "${CONTAINER_ID}:/upload_reset" "${OUTPUT_DIR}/" + +echo "" +echo "Step 5: Cleaning up container..." +docker rm "${CONTAINER_ID}" > /dev/null + +echo "" +echo "Step 6: Setting executable permissions..." +chmod +x "${OUTPUT_DIR}/dfu-util" +chmod +x "${OUTPUT_DIR}/dfu-prefix" +chmod +x "${OUTPUT_DIR}/dfu-suffix" +chmod +x "${OUTPUT_DIR}/hid-flash" +chmod +x "${OUTPUT_DIR}/upload_reset" + +echo "" +echo "Step 7: Verifying built binaries..." +echo "----------------------------------------" +file "${OUTPUT_DIR}/dfu-util" +file "${OUTPUT_DIR}/dfu-prefix" +file "${OUTPUT_DIR}/dfu-suffix" +file "${OUTPUT_DIR}/hid-flash" +file "${OUTPUT_DIR}/upload_reset" +echo "----------------------------------------" + +echo "" +echo "========================================" +echo "Build completed successfully!" +echo "========================================" +echo "" +echo "ARM64 binaries are now available in: ${OUTPUT_DIR}/" +echo "" +echo "All required binaries have been built:" +echo " - dfu-util, dfu-prefix, dfu-suffix (DFU programming)" +echo " - hid-flash (HID bootloader)" +echo " - upload_reset (Reset utility)" +echo "" +echo "Files in ${OUTPUT_DIR}:" +ls -lh "${OUTPUT_DIR}" diff --git a/src/linux-aarch64/clean.sh b/src/linux-aarch64/clean.sh new file mode 100755 index 000000000..8895e5eff --- /dev/null +++ b/src/linux-aarch64/clean.sh @@ -0,0 +1,79 @@ +#!/bin/bash +# +# Clean built ARM64 binaries from linux/aarch64/ +# + +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +OUTPUT_DIR="${REPO_ROOT}/linux/aarch64" + +echo "==========================================" +echo "Cleaning ARM64 Binaries" +echo "==========================================" +echo "" + +# List of binaries to remove +BINARIES=( + "dfu-util" + "dfu-prefix" + "dfu-suffix" + "hid-flash" + "upload_reset" +) + +echo "Output directory: ${OUTPUT_DIR}" +echo "" + +# Check which binaries exist +FILES_TO_REMOVE=() +for binary in "${BINARIES[@]}"; do + BINARY_PATH="${OUTPUT_DIR}/${binary}" + if [ -f "${BINARY_PATH}" ]; then + FILES_TO_REMOVE+=("${BINARY_PATH}") + fi +done + +# If no files to remove, exit +if [ ${#FILES_TO_REMOVE[@]} -eq 0 ]; then + echo "No binaries found to remove." + echo "Directory is already clean." + exit 0 +fi + +# Show what will be removed +echo "The following binaries will be removed:" +for file in "${FILES_TO_REMOVE[@]}"; do + echo " - $(basename ${file})" + if command -v file >/dev/null 2>&1; then + file "${file}" | sed 's/^/ /' + fi +done +echo "" + +# Ask for confirmation if interactive +if [ -t 0 ]; then + read -p "Continue? [y/N] " -n 1 -r + echo "" + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Cancelled." + exit 0 + fi +fi + +# Remove the binaries +echo "Removing binaries..." +for file in "${FILES_TO_REMOVE[@]}"; do + rm -f "${file}" + echo " ✓ Removed $(basename ${file})" +done + +echo "" +echo "==========================================" +echo "Clean completed successfully!" +echo "==========================================" +echo "" +echo "To rebuild the binaries, run:" +echo " ./build.sh" +echo ""