From fc01a31a1b212db148344b0a88be8348939c86bd Mon Sep 17 00:00:00 2001 From: john-1 Date: Tue, 5 May 2026 23:04:33 +0300 Subject: [PATCH 1/3] ci: build and publish u-boot artifacts to OpenIPC/firmware Mirrors the CI added to OpenIPC/u-boot-hi3519v101: per-SoC matrix (hi3518ev200, hi3516cv200), cached arm-hisiv510-linux toolchain from OpenIPC/toolchains v1, and a publish job that uploads u-boot--universal.bin to the 'latest' release in OpenIPC/firmware on push to master (with retry on transient 5xx). Also: Hi3518EV200 / Hi3516CV200 are Cortex-A7 (ARMv7-A); the cpu and board config.mk + compressed Makefile were forcing -march=armv5te as a historical workaround for old toolchains that didn't ship an armv7 multilib. The hisiv510 toolchain shipped in OpenIPC/toolchains only provides the armv7 multilib, so the armv5te flag broke the linker's libgcc lookup. Bump to -march=armv7-a in: - arch/arm/cpu/hi3518ev200/{config.mk, compressed/Makefile} - board/hi3516cv300/config.mk - board/hi3518ev200/config.mk Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/build.yml | 110 +++++++++++++++++++ arch/arm/cpu/hi3518ev200/compressed/Makefile | 2 +- arch/arm/cpu/hi3518ev200/config.mk | 7 +- board/hi3516cv300/config.mk | 2 +- board/hi3518ev200/config.mk | 2 +- 5 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..7c80454 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,110 @@ +name: Build + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + board: [hi3518ev200, hi3516cv200] + + steps: + - name: Install 32-bit libs + run: | + sudo dpkg --add-architecture i386 + sudo apt-get update -qq + sudo apt-get install -y -qq zlib1g:i386 libc6:i386 libstdc++6:i386 + + - name: Checkout + uses: actions/checkout@v4 + + - name: Cache toolchain + id: cache-tc + uses: actions/cache@v4 + with: + path: toolchain + key: arm-hisiv510-linux-v1 + + - name: Download toolchain + if: steps.cache-tc.outputs.cache-hit != 'true' + env: + GH_TOKEN: ${{ github.token }} + run: | + gh release download v1 -R OpenIPC/toolchains \ + -p 'arm-hisiv510-linux.tgz' + mkdir -p toolchain + tar xzf arm-hisiv510-linux.tgz -C toolchain + if [ -f toolchain/arm-hisiv510-linux/arm-hisiv510-linux.tar.bz2 ]; then + tar xjf toolchain/arm-hisiv510-linux/arm-hisiv510-linux.tar.bz2 -C toolchain + fi + rm arm-hisiv510-linux.tgz + # Create short-name symlinks (target/bin/ has absolute symlinks that won't work) + cd toolchain/arm-hisiv510-linux/bin + for f in arm-hisiv510-linux-uclibcgnueabi-*; do + ln -sf "$f" "${f/-uclibcgnueabi/}" + done + + - name: Build + run: | + export PATH="$PWD/toolchain/arm-hisiv510-linux/bin:$PATH" + make ${{ matrix.board }}_config + cp reg_info_${{ matrix.board }}.bin .reg + make CROSS_COMPILE=arm-hisiv510-linux- -j$(nproc) + make CROSS_COMPILE=arm-hisiv510-linux- mini-boot.bin + cp mini-boot.bin u-boot-${{ matrix.board }}-universal.bin + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: u-boot-${{ matrix.board }}-universal + path: u-boot-${{ matrix.board }}-universal.bin + + # Publish job — common failure modes: + # "GH_TOKEN environment variable required" / empty token: secret + # FIRMWARE_RELEASE_TOKEN is missing or unreadable. Set via the + # org-level Actions secret on OpenIPC. + # 401 Bad credentials: PAT expired (fine-grained max is 1 year) or + # revoked. Mint a new fine-grained PAT and update the secret. + # 403 Forbidden: PAT lacks Contents:write on OpenIPC/firmware, or + # its repo selector doesn't include OpenIPC/firmware. + # 404 on `gh release upload latest`: the `latest` tag was deleted in + # OpenIPC/firmware. Recreate it before retrying. + publish: + needs: build + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + runs-on: ubuntu-latest + steps: + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Upload to OpenIPC/firmware latest release + env: + GH_TOKEN: ${{ secrets.FIRMWARE_RELEASE_TOKEN }} + run: | + set -eu + # Releases API occasionally returns 502/503 ("Unicorn!"). Retry + # with linear backoff: 10s, 20s, 30s, 40s — total ~100s. + upload() { + local f="$1" i + for i in 1 2 3 4 5; do + if gh release upload latest "$f" --clobber -R OpenIPC/firmware; then + return 0 + fi + [ "$i" = "5" ] && return 1 + echo "upload attempt $i failed; sleeping $((i*10))s" >&2 + sleep $((i*10)) + done + } + for soc in hi3518ev200 hi3516cv200; do + f="artifacts/u-boot-${soc}-universal/u-boot-${soc}-universal.bin" + test -f "$f" + upload "$f" + done diff --git a/arch/arm/cpu/hi3518ev200/compressed/Makefile b/arch/arm/cpu/hi3518ev200/compressed/Makefile index 033c848..384c363 100644 --- a/arch/arm/cpu/hi3518ev200/compressed/Makefile +++ b/arch/arm/cpu/hi3518ev200/compressed/Makefile @@ -25,7 +25,7 @@ CFLAGS := -g -O2 -fno-strict-aliasing -fno-common -ffixed-r8 \ -fno-aggressive-loop-optimizations \ -mno-unaligned-access \ -pipe -DCONFIG_ARM -D__ARM__ -marm -mabi=aapcs-linux \ - -mno-thumb-interwork -march=armv5te $(MKFLAGS) + -mno-thumb-interwork -march=armv7-a $(MKFLAGS) ################################################################################ diff --git a/arch/arm/cpu/hi3518ev200/config.mk b/arch/arm/cpu/hi3518ev200/config.mk index 65c3b77..906dc4e 100644 --- a/arch/arm/cpu/hi3518ev200/config.mk +++ b/arch/arm/cpu/hi3518ev200/config.mk @@ -23,9 +23,12 @@ PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 # -msoft-float -# Make ARMv5 to allow more compilers to work, even though its v7a. +# Hi3518EV200 / Hi3516CV200 are Cortex-A7 (ARMv7-A). The historical +# armv5te downgrade was for old toolchains that didn't ship an armv7 +# multilib; the OpenIPC arm-hisiv510-linux toolchain does, so match the +# silicon and let the linker find libgcc. PLATFORM_RELFLAGS += -fno-aggressive-loop-optimizations -PLATFORM_CPPFLAGS += -march=armv5te +PLATFORM_CPPFLAGS += -march=armv7-a PLATFORM_CPPFLAGS += -mno-unaligned-access # ========================================================================= # diff --git a/board/hi3516cv300/config.mk b/board/hi3516cv300/config.mk index 59fc5e4..592fbc1 100644 --- a/board/hi3516cv300/config.mk +++ b/board/hi3516cv300/config.mk @@ -24,4 +24,4 @@ else TEXT_BASE = 0x88400000 endif -PLATFORM_CPPFLAGS += -march=armv5te -mno-unaligned-access -DTEXT_BASE=$(TEXT_BASE) +PLATFORM_CPPFLAGS += -march=armv7-a -mno-unaligned-access -DTEXT_BASE=$(TEXT_BASE) diff --git a/board/hi3518ev200/config.mk b/board/hi3518ev200/config.mk index 499a32d..97a6582 100644 --- a/board/hi3518ev200/config.mk +++ b/board/hi3518ev200/config.mk @@ -3,4 +3,4 @@ # TEXT_BASE = 0x80800000 -PLATFORM_CPPFLAGS += -march=armv5te -mno-unaligned-access -DTEXT_BASE=$(TEXT_BASE) +PLATFORM_CPPFLAGS += -march=armv7-a -mno-unaligned-access -DTEXT_BASE=$(TEXT_BASE) From 6701dda1536ff9d01d961fb2e7812b2a28fbfd54 Mon Sep 17 00:00:00 2001 From: john-1 Date: Wed, 6 May 2026 14:13:10 +0300 Subject: [PATCH 2/3] Revert -march bump: Hi3518EV200/Hi3516CV200 are ARM926EJ-S MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the ill-conceived -march=armv7-a from this branch. Hi3518EV200 and Hi3516CV200 are ARM926EJ-S (ARMv5TEJ), not Cortex-A7 — confirmed by widgetii/qemu-hisilicon's machine model and the kernel CPU detection. Restore -march=armv5te in the cpu, compressed Makefile, and both board config.mk files. Local rebuild produces a 135,420-byte mini-boot.bin tagged Tag_CPU_arch: v5TE (vs 2022 baseline 135,432, within noise). The CI workflow added in this PR is unaffected and stays. Co-Authored-By: Claude Opus 4.7 (1M context) --- arch/arm/cpu/hi3518ev200/compressed/Makefile | 2 +- arch/arm/cpu/hi3518ev200/config.mk | 8 +++----- board/hi3516cv300/config.mk | 2 +- board/hi3518ev200/config.mk | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/arch/arm/cpu/hi3518ev200/compressed/Makefile b/arch/arm/cpu/hi3518ev200/compressed/Makefile index 384c363..033c848 100644 --- a/arch/arm/cpu/hi3518ev200/compressed/Makefile +++ b/arch/arm/cpu/hi3518ev200/compressed/Makefile @@ -25,7 +25,7 @@ CFLAGS := -g -O2 -fno-strict-aliasing -fno-common -ffixed-r8 \ -fno-aggressive-loop-optimizations \ -mno-unaligned-access \ -pipe -DCONFIG_ARM -D__ARM__ -marm -mabi=aapcs-linux \ - -mno-thumb-interwork -march=armv7-a $(MKFLAGS) + -mno-thumb-interwork -march=armv5te $(MKFLAGS) ################################################################################ diff --git a/arch/arm/cpu/hi3518ev200/config.mk b/arch/arm/cpu/hi3518ev200/config.mk index 906dc4e..0e4ec42 100644 --- a/arch/arm/cpu/hi3518ev200/config.mk +++ b/arch/arm/cpu/hi3518ev200/config.mk @@ -23,12 +23,10 @@ PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 # -msoft-float -# Hi3518EV200 / Hi3516CV200 are Cortex-A7 (ARMv7-A). The historical -# armv5te downgrade was for old toolchains that didn't ship an armv7 -# multilib; the OpenIPC arm-hisiv510-linux toolchain does, so match the -# silicon and let the linker find libgcc. +# Hi3518EV200 / Hi3516CV200 are ARM926EJ-S (ARMv5TEJ), per the QEMU +# machine model in widgetii/qemu-hisilicon. Stay on armv5te to match. PLATFORM_RELFLAGS += -fno-aggressive-loop-optimizations -PLATFORM_CPPFLAGS += -march=armv7-a +PLATFORM_CPPFLAGS += -march=armv5te PLATFORM_CPPFLAGS += -mno-unaligned-access # ========================================================================= # diff --git a/board/hi3516cv300/config.mk b/board/hi3516cv300/config.mk index 592fbc1..59fc5e4 100644 --- a/board/hi3516cv300/config.mk +++ b/board/hi3516cv300/config.mk @@ -24,4 +24,4 @@ else TEXT_BASE = 0x88400000 endif -PLATFORM_CPPFLAGS += -march=armv7-a -mno-unaligned-access -DTEXT_BASE=$(TEXT_BASE) +PLATFORM_CPPFLAGS += -march=armv5te -mno-unaligned-access -DTEXT_BASE=$(TEXT_BASE) diff --git a/board/hi3518ev200/config.mk b/board/hi3518ev200/config.mk index 97a6582..499a32d 100644 --- a/board/hi3518ev200/config.mk +++ b/board/hi3518ev200/config.mk @@ -3,4 +3,4 @@ # TEXT_BASE = 0x80800000 -PLATFORM_CPPFLAGS += -march=armv7-a -mno-unaligned-access -DTEXT_BASE=$(TEXT_BASE) +PLATFORM_CPPFLAGS += -march=armv5te -mno-unaligned-access -DTEXT_BASE=$(TEXT_BASE) From 42e9f81761adb86d372aa14d3072d1d88b6520d1 Mon Sep 17 00:00:00 2001 From: john-1 Date: Wed, 6 May 2026 15:32:42 +0300 Subject: [PATCH 3/3] ci: add QEMU smoke test to gate publish MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same shape as the smoke test added in OpenIPC/u-boot-hi3516cv300: build qemu-system-arm from widgetii/qemu-hisilicon (cached by HEAD SHA), then run each matrix board's freshly-built u-boot in `-M hi3516cv200` (the ARM926EJ-S V2 family machine; both Hi3518EV200 and Hi3516CV200 binaries boot in the cv200 model since they share the SoC). Asserts u-boot prints past "System startup" — catches the class of regression where the binary's CFLAGS or TEXT_BASE don't match the silicon. publish now needs both build and qemu_smoke green. --- .github/workflows/build.yml | 88 ++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7c80454..3714057 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -65,6 +65,92 @@ jobs: name: u-boot-${{ matrix.board }}-universal path: u-boot-${{ matrix.board }}-universal.bin + # QEMU smoke test — gates publish on actually-bootable binaries. + # Boots the freshly-built u-boot in widgetii/qemu-hisilicon's + # machine model at the default RAM and asserts it prints past the + # legacy "System startup" banner. + qemu_smoke: + needs: build + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # Both binaries target V2-generation Hi3516CV200/Hi3518EV200 + # silicon (ARM926EJ-S); widgetii/qemu-hisilicon's + # `hi3516cv200` machine emulates that family. There is no + # standalone `hi3518ev200` machine — the binary boots fine in + # the cv200 model since they share the SoC. + include: + - { board: hi3518ev200, machine: hi3516cv200 } + - { board: hi3516cv200, machine: hi3516cv200 } + steps: + - name: Install QEMU build deps + run: | + sudo apt-get update -qq + sudo apt-get install -y -qq --no-install-recommends \ + build-essential ninja-build meson pkg-config \ + libglib2.0-dev libpixman-1-dev libfdt-dev zlib1g-dev \ + libslirp-dev python3 python3-venv + + - name: Resolve qemu-hisilicon HEAD + id: qemu-rev + run: | + sha=$(git ls-remote https://github.com/widgetii/qemu-hisilicon master | cut -f1) + echo "sha=$sha" >> "$GITHUB_OUTPUT" + + - name: Cache qemu-system-arm + id: cache-qemu + uses: actions/cache@v4 + with: + path: qemu-arm + key: qemu-hisilicon-${{ steps.qemu-rev.outputs.sha }} + + - name: Build qemu-system-arm (cache miss) + if: steps.cache-qemu.outputs.cache-hit != 'true' + run: | + git clone --depth 1 --branch master \ + https://github.com/widgetii/qemu-hisilicon qemu-hisilicon + cd qemu-hisilicon + bash qemu/setup.sh + cp qemu-src/build/qemu-system-arm "$GITHUB_WORKSPACE/qemu-arm" + chmod +x "$GITHUB_WORKSPACE/qemu-arm" + + - name: Download u-boot artifact + uses: actions/download-artifact@v4 + with: + name: u-boot-${{ matrix.board }}-universal + + - name: Smoke-test in QEMU + timeout-minutes: 2 + run: | + UBOOT="$PWD/u-boot-${{ matrix.board }}-universal.bin" + test -f "$UBOOT" + dd if=/dev/zero of=/tmp/flash.bin bs=1M count=8 2>/dev/null + dd if="$UBOOT" of=/tmp/flash.bin bs=1 conv=notrunc 2>/dev/null + mkfifo /tmp/uart.in /tmp/uart.out + chmod +x ./qemu-arm + ./qemu-arm \ + -M ${{ matrix.machine }} \ + -global hisi-fmc.flash-file=/tmp/flash.bin \ + -nographic -serial pipe:/tmp/uart \ + -monitor none > /tmp/qemu.log 2>&1 & + QEMU_PID=$! + timeout 10 cat /tmp/uart.out > /tmp/uboot.txt || true + kill "$QEMU_PID" 2>/dev/null || true + wait 2>/dev/null || true + echo "== captured u-boot output ==" + cat /tmp/uboot.txt + echo + if grep -qE 'U-Boot |Hit any key|CPU:|DRAM:|Board:' /tmp/uboot.txt; then + echo "PASS: u-boot booted past System startup" + else + echo "FAIL: u-boot did not get past System startup" + echo + echo "== qemu stderr ==" + tail -40 /tmp/qemu.log || true + exit 1 + fi + # Publish job — common failure modes: # "GH_TOKEN environment variable required" / empty token: secret # FIRMWARE_RELEASE_TOKEN is missing or unreadable. Set via the @@ -76,7 +162,7 @@ jobs: # 404 on `gh release upload latest`: the `latest` tag was deleted in # OpenIPC/firmware. Recreate it before retrying. publish: - needs: build + needs: [build, qemu_smoke] if: github.event_name == 'push' && github.ref == 'refs/heads/master' runs-on: ubuntu-latest steps: