name: Build on: push: pull_request: workflow_dispatch: env: MAKEFLAGS: "-j4 GITVERSION=${{ github.sha }}" jobs: bios: name: BIOS / ${{ matrix.arch }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: arch: - i386 - x86_64 container: image: ghcr.io/ipxe/ipxe-builder-${{ matrix.arch }} env: bindir: >- ${{ matrix.arch == 'i386' && 'bin' || 'bin-x86_64-pcbios' }} steps: - name: Check out code uses: actions/checkout@v6 - name: Build working-directory: src run: | make ${{ env.bindir }}/10ec8139.rom \ ${{ env.bindir }}/8086100e.mrom \ ${{ env.bindir }}/ipxe.dsk \ ${{ env.bindir }}/ipxe.iso \ ${{ env.bindir }}/ipxe.lkrn \ ${{ env.bindir }}/ipxe.pxe \ ${{ env.bindir }}/ipxe.usb \ ${{ env.bindir }}/ipxe-legacy.lkrn \ ${{ env.bindir }}/ipxe-legacy.pxe \ ${{ env.bindir }}/undionly.kpxe \ ${{ env.bindir }}/errors - name: Hardware list working-directory: src run: | ./util/niclist.pl \ --format dokuwiki \ --sort bus-,vendor_id,device_id,device_name \ --output ${{ env.bindir }}/niclist.txt - name: Upload uses: actions/upload-artifact@v6 with: name: ${{ env.bindir }} if-no-files-found: error path: | src/${{ env.bindir }}/ipxe.lkrn src/${{ env.bindir }}/ipxe.pxe src/${{ env.bindir }}/ipxe-legacy.lkrn src/${{ env.bindir }}/ipxe-legacy.pxe src/${{ env.bindir }}/undionly.kpxe src/${{ env.bindir }}/errors src/${{ env.bindir }}/niclist.txt sbi: name: SBI / ${{ matrix.arch }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: arch: - riscv32 - riscv64 container: image: ghcr.io/ipxe/ipxe-builder-${{ matrix.arch }} env: bindir: bin-${{ matrix.arch }} steps: - name: Check out code uses: actions/checkout@v6 - name: Build working-directory: src run: | make ${{ env.bindir }}/ipxe.pf32 \ ${{ env.bindir }}/ipxe.lkrn \ ${{ env.bindir }}/ipxe.sbi \ ${{ env.bindir }}/errors - name: Upload uses: actions/upload-artifact@v6 with: name: ${{ env.bindir }} if-no-files-found: error path: | src/${{ env.bindir }}/ipxe.lkrn src/${{ env.bindir }}/ipxe.sbi src/${{ env.bindir }}/errors uefi: name: UEFI / ${{ matrix.arch }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: arch: - arm32 - arm64 - i386 - loong64 - riscv32 - riscv64 - x86_64 container: image: ghcr.io/ipxe/ipxe-builder-${{ matrix.arch }} env: bindir: bin-${{ matrix.arch }}-efi steps: - name: Check out code uses: actions/checkout@v6 - name: Build working-directory: src run: | make ${{ env.bindir }}/ipxe.efi \ ${{ env.bindir }}/ipxe.iso \ ${{ env.bindir }}/ipxe.usb \ ${{ env.bindir }}/ipxe-legacy.efi \ ${{ env.bindir }}/snponly.efi \ ${{ env.bindir }}/errors - name: Upload uses: actions/upload-artifact@v6 with: name: ${{ env.bindir }} if-no-files-found: error path: | src/${{ env.bindir }}/ipxe.efi src/${{ env.bindir }}/ipxe-legacy.efi src/${{ env.bindir }}/snponly.efi src/${{ env.bindir }}/errors uefi-sb: name: UEFI SB / ${{ matrix.arch }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: arch: - arm64 - x86_64 container: image: ghcr.io/ipxe/ipxe-builder-${{ matrix.arch }} env: bindir: bin-${{ matrix.arch }}-efi-sb outputs: sbsignenv: ${{ steps.sbsignenv.outputs.sbsignenv }} steps: - name: Check out code uses: actions/checkout@v6 - name: Build working-directory: src run: | make ${{ env.bindir }}/ipxe.efi \ ${{ env.bindir }}/snponly.efi - name: Upload uses: actions/upload-artifact@v6 with: name: unsigned-${{ env.bindir }} if-no-files-found: error path: | src/${{ env.bindir }}/ipxe.efi src/${{ env.bindir }}/snponly.efi - name: Select environment id: sbsignenv if: >- github.ref == 'refs/heads/sbsign' || startsWith ( github.ref, 'refs/tags/v' ) run: | echo "sbsignenv=${{ vars.SBSIGN_ENVIRONMENT }}" >> $GITHUB_OUTPUT sbsign: name: SB Sign / ${{ matrix.arch }} runs-on: ${{ needs.uefi-sb.outputs.sbsignenv || 'ubuntu-latest' }} needs: - uefi-sb strategy: fail-fast: false matrix: arch: - arm64 - x86_64 container: image: ghcr.io/ipxe/ipxe-signer volumes: - run-pcscd:/run/pcscd services: pcscd: image: ghcr.io/ipxe/ipxe-signer-pcscd volumes: - run-pcscd:/run/pcscd options: >- ${{ needs.uefi-sb.outputs.sbsignenv && '--device /dev/bus/usb' }} --label OPTIONS_VALUE_CANNOT_BE_EMPTY=1 env: binaries: >- ipxe.efi snponly.efi bindir: bin-${{ matrix.arch }}-efi-sb cacert: ${{ vars.SBSIGN_CA_CERT || 'testsign.crt' }} pkcs11: ${{ secrets.SBSIGN_PASSWORD && 'true' }} signcerts: ${{ vars.SBSIGN_CERTS || 'testsign.crt' }} signkey: ${{ vars.SBSIGN_KEY || 'testsign.key' }} signpass: ${{ secrets.SBSIGN_PASSWORD || 'testpw' }} environment: ${{ needs.uefi-sb.outputs.sbsignenv }} steps: - name: Check out code uses: actions/checkout@v6 with: repository: ipxe/secure-boot-ca - name: Download uses: actions/download-artifact@v7 with: name: unsigned-${{ env.bindir }} path: unsigned - name: Test certificate run: | COMMITID=$(echo ${{ github.sha }} | cut -c1-9) SUBJECT="iPXE Test Signing (${COMMITID}, ${{ matrix.arch }})" openssl req \ -newkey rsa:2048 -passout 'pass:testpw' -keyout testsign.key \ -subj "/CN=${SUBJECT}/" -x509 -out testsign.crt - name: Certificate chain run: | for cert in ${{ env.signcerts }} ; do openssl x509 -in ${cert} -noout -text cat ${cert} >> chain.crts done - name: Sign run: | for binary in ${{ env.binaries }} ; do osslsigncode sign \ ${{ env.pkcs11 && '-pkcs11module' }} \ ${{ env.pkcs11 && '/usr/lib64/opensc-pkcs11.so' }} \ -certs chain.crts \ -key ${{ env.signkey }} \ -pass ${{ env.signpass }} \ -ts http://timestamp.digicert.com \ -in unsigned/${binary} \ -out ${binary} done - name: Verify run: | for binary in ${{ env.binaries }} ; do osslsigncode verify -CAfile ${{ env.cacert }} ${binary} done - name: Upload uses: actions/upload-artifact@v6 with: name: ${{ env.bindir }} if-no-files-found: error path: | ${{ env.cacert }} ipxe.efi snponly.efi linux: name: Linux / ${{ matrix.arch }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: include: - arch: arm32 exec: qemu-arm-static - arch: arm64 exec: qemu-aarch64-static - arch: i386 exec: valgrind - arch: loong64 exec: qemu-loongarch64-static - arch: riscv32 exec: qemu-riscv32-static - arch: riscv64 exec: qemu-riscv64-static - arch: x86_64 exec: valgrind container: image: ghcr.io/ipxe/ipxe-builder-${{ matrix.arch }} env: bindir: bin-${{ matrix.arch }}-linux steps: - name: Check out code uses: actions/checkout@v6 - name: Build working-directory: src run: | make ${{ env.bindir }}/ipxe.linux \ ${{ env.bindir }}/tests.linux \ ${{ env.bindir }}/errors - name: Upload uses: actions/upload-artifact@v6 with: name: ${{ env.bindir }} if-no-files-found: error path: | src/${{ env.bindir }}/ipxe.linux src/${{ env.bindir }}/tests.linux src/${{ env.bindir }}/errors - name: Test working-directory: src run: | ${{ matrix.exec }} ${{ env.bindir }}/tests.linux shim: name: UEFI shim runs-on: ubuntu-latest env: shims: >- shimaa64.efi shimx64.efi shimurl: >- https://github.com/ipxe/shim/releases/latest/download steps: - name: Download run: | for shim in ${{ env.shims }} ; do curl -L ${{ env.shimurl }}/ipxe-${shim} -o ${shim} done - name: Upload uses: actions/upload-artifact@v6 with: name: shim if-no-files-found: error path: | shimaa64.efi shimx64.efi combine: name: BIOS + UEFI runs-on: ubuntu-latest needs: - bios - uefi - sbsign - shim container: image: ghcr.io/ipxe/ipxe-builder-utils env: binaries: >- bin-x86_64-pcbios/${DRIVERS}.lkrn bin-arm32-efi/${DRIVERS}.efi bin-arm64-efi/${DRIVERS}.efi bin-i386-efi/${DRIVERS}.efi bin-loong64-efi/${DRIVERS}.efi bin-riscv32-efi/${DRIVERS}.efi bin-riscv64-efi/${DRIVERS}.efi bin-x86_64-efi/${DRIVERS}.efi steps: - name: Check out code uses: actions/checkout@v6 - name: Download uses: actions/download-artifact@v7 with: pattern: "{bin-x86_64-pcbios,bin-*-efi,bin-*-efi-sb,shim}" - name: Combine run: | # Provide an editable placeholder autoexec.ipxe for the USB image cat > autoexec.ipxe <<'EOF' #!ipxe echo prompt --key 0x02 --timeout 2000 \ Press Ctrl-B for the iPXE command line... \ && shell || autoboot EOF for DRIVERS in ipxe ipxe-legacy ; do ./src/util/genfsimg -o ${DRIVERS}.iso ${{ env.binaries }} ./src/util/genfsimg -o ${DRIVERS}.usb -s autoexec.ipxe \ ${{ env.binaries }} done - name: Upload uses: actions/upload-artifact@v6 with: name: bin-combi if-no-files-found: error path: | ipxe.iso ipxe.usb ipxe-legacy.iso ipxe-legacy.usb netboot: name: Netboot runs-on: ubuntu-latest needs: - bios - uefi - sbsign - shim container: image: ghcr.io/ipxe/ipxe-builder-utils env: biosarchs: >- i386:bin x86_64:bin-x86_64-pcbios biosfiles: >- ipxe.pxe ipxe-legacy.pxe undionly.kpxe efiarchs: >- arm32 arm64 i386 loong64 riscv32 riscv64 x86_64 efifiles: >- ipxe.efi ipxe-legacy.efi snponly.efi sbarchs: >- arm64:aa64 x86_64:x64 sbfiles: >- ipxe.efi snponly.efi steps: - name: Download uses: actions/download-artifact@v7 with: pattern: "{bin,bin-x86_64-pcbios,bin-*-efi,bin-*-efi-sb,shim}" - name: BIOS run: | for biosarch in ${{ env.biosarchs }} ; do IFS=: read -r arch bindir <<< "${biosarch}" mkdir -p ipxeboot/${arch} for file in ${{ env.biosfiles }} ; do cp ${bindir}/${file} ipxeboot/${arch}/${file} ln -sf x86_64/${file} ipxeboot/${file} done done - name: UEFI run: | for arch in ${{ env.efiarchs }} ; do mkdir -p ipxeboot/${arch} for file in ${{ env.efifiles }} ; do cp bin-${arch}-efi/${file} ipxeboot/${arch}/${file} ln -sf x86_64/${file} ipxeboot/${file} done done - name: UEFI SB run: | for sbarch in ${{ env.sbarchs }} ; do IFS=: read -r arch efiarch <<< ${sbarch} mkdir -p ipxeboot/${arch}-sb shimfile=shim${efiarch}.efi cp shim/${shimfile} ipxeboot/${arch}-sb/${shimfile} for file in ${{ env.sbfiles }} ; do shimlink=${file/.efi/-shim.efi} cp bin-${arch}-efi-sb/${file} ipxeboot/${arch}-sb/${file} ln -sf ${shimfile} ipxeboot/${arch}-sb/${shimlink} done done ln -sf x86_64-sb ipxeboot/sb - name: Archive run: | tar cvzf ipxeboot.tar.gz ipxeboot - name: Upload uses: actions/upload-artifact@v6 with: name: netboot if-no-files-found: error path: | ipxeboot.tar.gz version: name: Version runs-on: ubuntu-latest container: image: ghcr.io/ipxe/ipxe-builder-utils env: bindir: bin steps: - name: Check out code uses: actions/checkout@v6 - name: Build working-directory: src run: | make REPOURL=${{ github.server_url }}/${{ github.repository }} \ ${{ env.bindir }}/version.txt \ ${{ env.bindir }}/relname.txt \ ${{ env.bindir }}/reltitle.txt \ ${{ env.bindir }}/relnotes.md - name: Upload uses: actions/upload-artifact@v6 with: name: version if-no-files-found: error path: | src/${{ env.bindir }}/version.txt src/${{ env.bindir }}/relname.txt src/${{ env.bindir }}/reltitle.txt src/${{ env.bindir }}/relnotes.md publish: name: Publish runs-on: ubuntu-latest needs: - bios - sbi - uefi - sbsign - linux - shim - combine - netboot - version if: >- github.ref == 'refs/heads/master' && vars.PAGES_REPO_NAME env: workflow_url: >- ${{ github.server_url }}/${{ vars.PAGES_REPO_OWNER }}/${{ '' }}${{ vars.PAGES_REPO_NAME }}/actions/workflows/build.yml environment: name: publish url: ${{ env.workflow_url }} steps: - name: Get token id: token uses: actions/create-github-app-token@v2 with: app-id: ${{ vars.WORKFLOW_DISPATCHER_ID }} private-key: ${{ secrets.WORKFLOW_DISPATCHER_KEY }} owner: ${{ vars.PAGES_REPO_OWNER }} repositories: ${{ vars.PAGES_REPO_NAME }} - name: Dispatch env: GH_REPO: ${{ vars.PAGES_REPO_OWNER }}/${{ vars.PAGES_REPO_NAME }} GH_TOKEN: ${{ steps.token.outputs.token }} run: | gh workflow run build.yml -f run_id=${{ github.run_id }} echo "Results at ${{ env.workflow_url }}" release: name: Release runs-on: ubuntu-latest needs: - bios - sbi - uefi - sbsign - linux - shim - combine - netboot - version if: >- startsWith ( github.ref, 'refs/tags/v' ) steps: - name: Download uses: actions/download-artifact@v7 with: pattern: "{bin-combi,netboot,version}" - name: Tag check run: | RELNAME=$(cat version/relname.txt) if [ "${{ github.ref_name }}" != "${RELNAME}" ] ; then echo "ERROR: Tag does not match release name ${RELNAME}" >&2 exit 1 fi - name: Release env: GH_REPO: ${{ github.repository }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh release create "${{ github.ref_name }}" --verify-tag --draft \ --title "$(cat version/relname.txt)" \ --notes-file version/relnotes.md \ bin-combi/ipxe.iso bin-combi/ipxe.usb netboot/ipxeboot.tar.gz