Examples
There is a separate directory with examples called firmware-action-example. It is a great source of information to get started.
In addition, the main repository also contains multiple examples (even though rather simple ones) defined in .github/workflows/example.yml. These are there to function as tests to verify the functionality, as such they are made with this specific task in mind. Please take that into account when going though them.
Coreboot
Coreboot - GitHub CI
Coreboot - GitHub CI
build-coreboot:
needs:
- changes
- skip-check
strategy:
fail-fast: false
matrix:
coreboot-version: ['24.02.01']
arch: ['amd64', 'arm64']
runs-on: ${{ matrix.arch == 'arm64' && 'ARM64' || 'ubuntu-latest' }}
if: ${{ ! (github.event_name == 'pull_request_review' && github.actor != 'github-actions[bot]') && needs.skip-check.outputs.changes == 'true' }}
# Skip if pull_request_review on PR not made by a bot
steps:
- name: Cleanup
run: |
rm -rf ./* || true
rm -rf ./.??* || true
- name: Checkout
uses: actions/checkout@v4
- name: Restore cached coreboot repo
uses: actions/cache/restore@v4
id: cache-repo
with:
path: ./my_super_dooper_awesome_coreboot
key: coreboot-${{ matrix.coreboot-version }}-example
- name: Clone coreboot repo
if: steps.cache-repo.outputs.cache-hit != 'true'
run: |
git clone --branch "${{ matrix.coreboot-version }}" --depth 1 https://review.coreboot.org/coreboot my_super_dooper_awesome_coreboot
- name: Store coreboot repo in cache
uses: actions/cache/save@v4
if: steps.cache-repo.outputs.cache-hit != 'true'
with:
path: ./my_super_dooper_awesome_coreboot
key: coreboot-${{ matrix.coreboot-version }}-example
- name: Move my defconfig into place (filename must not contain '.defconfig')
run: |
mv "tests/coreboot_${{ matrix.coreboot-version }}/seabios.defconfig" "seabios_defconfig"
- name: firmware-action
uses: ./
# uses: 9elements/firmware-action
with:
config: |-
tests/example_config__coreboot.json
tests/example_config__uroot.json
target: 'coreboot-example'
recursive: 'false'
compile: ${{ needs.changes.outputs.compile }}
debug: 'true'
enable-cache: 'true'
auto-download-artifacts: 'true'
auto-upload-artifacts: 'true'
env:
COREBOOT_VERSION: ${{ matrix.coreboot-version }}
UROOT_VERSION: 'dummy'
Coreboot - Configuration file
Coreboot - Configuration file
{
"coreboot": {
"coreboot-example": {
"depends": null,
"sdk_url": "ghcr.io/9elements/firmware-action/coreboot_${COREBOOT_VERSION}:main",
"repo_path": "my_super_dooper_awesome_coreboot/",
"defconfig_path": "seabios_defconfig",
"output_dir": "output-coreboot/",
"container_output_dirs": null,
"container_output_files": ["build/coreboot.rom", "defconfig"],
"blobs": {},
"container_input_dir": "inputs/",
"input_dirs": null,
"input_files": null
}
}
}
Linux Kernel
Linux Kernel - GitHub CI
Linux Kernel - GitHub CI
build-linux:
needs:
- changes
- skip-check
strategy:
fail-fast: false
matrix:
linux-version: ['6.12']
arch: ['amd64', 'arm64']
runs-on: ${{ matrix.arch == 'arm64' && 'ARM64' || 'ubuntu-latest' }}
if: ${{ ! (github.event_name == 'pull_request_review' && github.actor != 'github-actions[bot]') && needs.skip-check.outputs.changes == 'true' }}
# Skip if pull_request_review on PR not made by a bot
steps:
- name: Cleanup
run: |
rm -rf ./* || true
rm -rf ./.??* || true
- name: Checkout
uses: actions/checkout@v4
- name: Restore cached linux source
id: cache-repo
uses: actions/cache/restore@v4
with:
path: ./linux-${{ matrix.linux-version }}.tar.xz
key: linux-${{ matrix.linux-version }}-example
- name: Prepare linux kernel
run: |
# Download source files
wget --quiet --continue "https://cdn.kernel.org/pub/linux/kernel/v${LINUX_MAJOR_VERSION}.x/linux-${{ matrix.linux-version }}.tar.xz"
wget --quiet "https://cdn.kernel.org/pub/linux/kernel/v${LINUX_MAJOR_VERSION}.x/linux-${{ matrix.linux-version }}.tar.sign"
unxz --keep "linux-${{ matrix.linux-version }}.tar.xz" >/dev/null
# Verify GPG signature
gpg2 --locate-keys torvalds@kernel.org gregkh@kernel.org
gpg2 --verify "linux-${{ matrix.linux-version }}.tar.sign"
# Extract
tar -xvf "linux-${{ matrix.linux-version }}.tar"
env:
LINUX_MAJOR_VERSION: 6
- name: Store linux source in cache
uses: actions/cache/save@v4
if: steps.cache-repo.outputs.cache-hit != 'true'
with:
path: ./linux-${{ matrix.linux-version }}.tar.xz
key: linux-${{ matrix.linux-version }}-example
- name: Move my defconfig into place (filename must not contain '.defconfig')
run: |
mv "tests/linux_${{ matrix.linux-version }}/linux.defconfig" "ci_defconfig"
- name: firmware-action
uses: ./
# uses: 9elements/firmware-action
with:
config: |-
tests/example_config__uroot.json
tests/example_config__linux.json
target: 'linux-example'
recursive: 'false'
compile: ${{ needs.changes.outputs.compile }}
debug: 'true'
enable-cache: 'true'
auto-download-artifacts: 'true'
auto-upload-artifacts: 'true'
env:
LINUX_VERSION: ${{ matrix.linux-version }}
SYSTEM_ARCH: ${{ matrix.arch }}
UROOT_VERSION: 'dummy'
Linux Kernel - Configuration file
Linux Kernel - Configuration file
{
"linux": {
"linux-example": {
"depends": null,
"sdk_url": "ghcr.io/9elements/firmware-action/linux_${LINUX_VERSION}:main",
"arch": "${SYSTEM_ARCH}",
"repo_path": "linux-${LINUX_VERSION}/",
"defconfig_path": "ci_defconfig",
"output_dir": "output-linux/",
"container_output_dirs": null,
"container_output_files": ["vmlinux", "defconfig"],
"gcc_version": "",
"container_input_dir": "inputs/",
"input_dirs": null,
"input_files": null
}
}
}
Edk2
Edk2 - GitHub CI
Edk2 - GitHub CI
build-edk2:
runs-on: ubuntu-latest
needs:
- changes
- skip-check
strategy:
fail-fast: false
matrix:
edk2-version: ['edk2-stable202211']
# TODO
if: ${{ ! (github.event_name == 'pull_request_review' && github.actor != 'github-actions[bot]') && needs.skip-check.outputs.changes == 'true' }}
# Skip if pull_request_review on PR not made by a bot
steps:
- name: Cleanup
run: |
rm -rf ./* || true
rm -rf ./.??* || true
- name: Checkout
uses: actions/checkout@v4
- name: Restore cached edk2 repo
uses: actions/cache/restore@v4
id: cache-repo
with:
path: ./Edk2
key: edk2-${{ matrix.edk2-version }}-example
- name: Clone edk2 repo
if: steps.cache-repo.outputs.cache-hit != 'true'
run: |
git clone --recurse-submodules --branch "${{ matrix.edk2-version }}" --depth 1 https://github.com/tianocore/edk2.git Edk2
- name: Prepare file with build arguments
run: |
echo "-D BOOTLOADER=COREBOOT -D TPM_ENABLE=TRUE -D NETWORK_IPXE=TRUE" > "edk2_config.cfg"
- name: Store edk2 repo in cache
uses: actions/cache/save@v4
if: steps.cache-repo.outputs.cache-hit != 'true'
with:
path: ./Edk2
key: edk2-${{ matrix.edk2-version }}-example
- name: Get versions of edk2
id: edk2_versions
run: |
echo "ver_current=$( echo ${{ matrix.edk2-version }} | tr -cd '0-9' )" >> "${GITHUB_OUTPUT}"
echo "ver_breaking=$( echo 'edk2-stable202305' | tr -cd '0-9' )" >> "${GITHUB_OUTPUT}"
- name: Use GCC5 for old edk2
id: gcc_toolchain
# GCC5 is deprecated since edk2-stable202305
# For more information see https://github.com/9elements/firmware-action/issues/340
run: |
if [[ ! ${{ steps.edk2_versions.outputs.ver_current }} < ${{ steps.edk2_versions.outputs.ver_breaking }} ]]; then
echo "gcc_toolchain_version=GCC" >> "${GITHUB_OUTPUT}"
else
echo "gcc_toolchain_version=GCC5" >> "${GITHUB_OUTPUT}"
fi
- name: firmware-action
uses: ./
# uses: 9elements/firmware-action
with:
config: 'tests/example_config__edk2.json'
target: 'edk2-example'
recursive: 'false'
compile: ${{ needs.changes.outputs.compile }}
debug: 'true'
enable-cache: 'true'
auto-download-artifacts: 'true'
auto-upload-artifacts: 'true'
env:
EDK2_VERSION: ${{ matrix.edk2-version }}
GCC_TOOLCHAIN_VERSION: ${{ steps.gcc_toolchain.outputs.gcc_toolchain_version }}
Edk2 - Configuration file
Edk2 - Configuration file
{
"edk2": {
"edk2-example": {
"depends": null,
"sdk_url": "ghcr.io/9elements/firmware-action/${EDK2_VERSION}:main",
"arch": "X64",
"repo_path": "Edk2/",
"defconfig_path": "edk2_config.cfg",
"output_dir": "output-edk2/",
"container_output_dirs": ["Build/"],
"container_output_files": null,
"build_command": "source ./edksetup.sh; build -a X64 -p UefiPayloadPkg/UefiPayloadPkg.dsc -b DEBUG -t ${GCC_TOOLCHAIN_VERSION}",
"container_input_dir": "inputs/",
"input_dirs": null,
"input_files": null
}
}
}
Firmware Stitching
Firmware Stitching - GitHub CI
Firmware Stitching - GitHub CI
build-stitching:
needs:
- changes
- skip-check
strategy:
fail-fast: false
matrix:
coreboot-version: ['4.19']
arch: ['amd64', 'arm64']
runs-on: ${{ matrix.arch == 'arm64' && 'ARM64' || 'ubuntu-latest' }}
if: ${{ ! (github.event_name == 'pull_request_review' && github.actor != 'github-actions[bot]') && needs.skip-check.outputs.changes == 'true' }}
# Skip if pull_request_review on PR not made by a bot
steps:
- name: Cleanup
run: |
rm -rf ./* || true
rm -rf ./.??* || true
- name: Checkout
uses: actions/checkout@v4
- name: Restore cached coreboot-blobs repo
uses: actions/cache/restore@v4
id: cache-repo
with:
path: ./stitch
key: coreboot-blobs-${{ matrix.coreboot-version }}-example
- name: Clone blobs repo
if: steps.cache-repo.outputs.cache-hit != 'true'
run: |
git clone --depth 1 https://review.coreboot.org/blobs stitch
- name: Store coreboot-blobs repo in cache
uses: actions/cache/save@v4
if: steps.cache-repo.outputs.cache-hit != 'true'
with:
path: ./stitch
key: coreboot-blobs-${{ matrix.coreboot-version }}-example
- name: firmware-action
uses: ./
# uses: 9elements/firmware-action
with:
config: 'tests/example_config__firmware_stitching.json'
target: 'stitching-example'
recursive: 'false'
compile: ${{ needs.changes.outputs.compile }}
debug: 'true'
enable-cache: 'true'
auto-download-artifacts: 'true'
auto-upload-artifacts: 'true'
env:
COREBOOT_VERSION: ${{ matrix.coreboot-version }}
Firmware Stitching - Configuration file
Firmware Stitching - Configuration file
{
"firmware_stitching": {
"stitching-example": {
"depends": null,
"sdk_url": "ghcr.io/9elements/firmware-action/coreboot_${COREBOOT_VERSION}:main",
"repo_path": "stitch/",
"container_output_dirs": null,
"container_output_files": ["new_descriptor.bin"],
"output_dir": "output-stitch/",
"base_file_path": "stitch/mainboard/intel/emeraldlake2/descriptor.bin",
"platform": "",
"ifdtool_entries": [
{
"path": "stitch/mainboard/intel/emeraldlake2/me.bin",
"target_region": "ME",
"optional_arguments": null
}
],
"container_input_dir": "inputs/",
"input_dirs": null,
"input_files": null
}
}
}
u-root
u-root - GitHub CI
u-root - GitHub CI
build-uroot:
needs:
- changes
- skip-check
strategy:
fail-fast: false
matrix:
uroot-version: ['0.14.0']
arch: ['amd64', 'arm64']
runs-on: ${{ matrix.arch == 'arm64' && 'ARM64' || 'ubuntu-latest' }}
if: ${{ ! (github.event_name == 'pull_request_review' && github.actor != 'github-actions[bot]') && needs.skip-check.outputs.changes == 'true' }}
# Skip if pull_request_review on PR not made by a bot
steps:
- name: Cleanup
run: |
rm -rf ./* || true
rm -rf ./.??* || true
- name: Checkout
uses: actions/checkout@v4
- name: Restore cached u-root repo
uses: actions/cache/restore@v4
id: cache-repo
with:
path: ./u-root
key: u-root-${{ matrix.uroot-version }}-example
- name: Clone u-root repo
if: steps.cache-repo.outputs.cache-hit != 'true'
run: |
git clone --depth 1 --branch v${{ matrix.uroot-version }} https://github.com/u-root/u-root.git || true
- name: Store u-root repo in cache
uses: actions/cache/save@v4
if: steps.cache-repo.outputs.cache-hit != 'true'
with:
path: ./u-root
key: u-root-${{ matrix.uroot-version }}-example
- name: firmware-action
uses: ./
# uses: 9elements/firmware-action
with:
config: 'tests/example_config__uroot.json'
target: 'u-root-example'
recursive: 'false'
compile: ${{ needs.changes.outputs.compile }}
debug: 'true'
enable-cache: 'true'
auto-download-artifacts: 'true'
auto-upload-artifacts: 'true'
env:
UROOT_VERSION: ${{ matrix.uroot-version }}
u-root - Configuration file
u-root - Configuration file
{
"u-root": {
"u-root-example": {
"depends": null,
"sdk_url": "ghcr.io/9elements/firmware-action/uroot_${UROOT_VERSION}:main",
"repo_path": "u-root/",
"output_dir": "output-uroot/",
"container_output_dirs": null,
"container_output_files": ["initramfs.cpio"],
"build_command": "go build; GOARCH=amd64 ./u-root -defaultsh gosh -o initramfs.cpio boot coreboot-app ./cmds/core/* ./cmds/boot/*",
"container_input_dir": "inputs/",
"input_dirs": null,
"input_files": null
}
}
}
u-boot
u-boot - GitHub CI
u-boot - GitHub CI
build-uboot:
needs:
- changes
- skip-check
strategy:
fail-fast: false
matrix:
uboot-version: ['2025.01']
arch: ['amd64', 'arm64']
runs-on: ${{ matrix.arch == 'arm64' && 'ARM64' || 'ubuntu-latest' }}
if: ${{ ! (github.event_name == 'pull_request_review' && github.actor != 'github-actions[bot]') && needs.skip-check.outputs.changes == 'true' }}
# Skip if pull_request_review on PR not made by a bot
steps:
- name: Cleanup
run: |
rm -rf ./* || true
rm -rf ./.??* || true
- name: Checkout
uses: actions/checkout@v4
- name: Restore cached u-boot repo
uses: actions/cache/restore@v4
id: cache-repo
with:
path: ./u-boot
key: u-boot-${{ matrix.uboot-version }}-example
- name: Clone u-boot repo
if: steps.cache-repo.outputs.cache-hit != 'true'
run: |
git clone https://source.denx.de/u-boot/u-boot.git
cd u-boot
git fetch -a
git checkout "v${{ matrix.uboot-version }}"
- name: Store u-boot repo in cache
uses: actions/cache/save@v4
if: steps.cache-repo.outputs.cache-hit != 'true'
with:
path: ./u-boot
key: u-boot-${{ matrix.uboot-version }}-example
- name: Move my defconfig into place (filename must not contain '.defconfig')
run: |
mv "tests/uboot_${{ matrix.uboot-version }}/uboot.defconfig" "uboot_defconfig"
- name: firmware-action
uses: ./
# uses: 9elements/firmware-action
with:
config: 'tests/example_config__uboot.json'
target: 'u-boot-example'
recursive: 'false'
compile: ${{ needs.changes.outputs.compile }}
debug: 'true'
enable-cache: 'true'
auto-download-artifacts: 'true'
auto-upload-artifacts: 'true'
env:
UBOOT_VERSION: ${{ matrix.uboot-version }}
u-boot - Configuration file
u-boot - Configuration file
{
"u-boot": {
"u-boot-example": {
"depends": null,
"sdk_url": "ghcr.io/9elements/firmware-action/uboot_${UBOOT_VERSION}:main",
"arch": "arm64",
"repo_path": "u-boot/",
"defconfig_path": "uboot_defconfig",
"output_dir": "output-uboot/",
"container_output_dirs": null,
"container_output_files": ["u-boot", "u-boot.cfg", "u-boot.elf"],
"container_input_dir": "inputs/",
"input_dirs": null,
"input_files": null
}
}
}
Universal
Universal - GitHub CI
Universal - GitHub CI
build-universal:
needs:
- changes
- skip-check
runs-on: ubuntu-latest
if: ${{ ! (github.event_name == 'pull_request_review' && github.actor != 'github-actions[bot]') && needs.skip-check.outputs.changes == 'true' }}
# Skip if pull_request_review on PR not made by a bot
steps:
- name: Cleanup
run: |
rm -rf ./* || true
rm -rf ./.??* || true
- name: Checkout
uses: actions/checkout@v4
- name: firmware-action
uses: ./
# uses: 9elements/firmware-action
with:
config: 'tests/example_config__universal.json'
target: 'universal-example'
recursive: 'false'
compile: ${{ needs.changes.outputs.compile }}
- name: Get artifacts
uses: actions/upload-artifact@v4
with:
name: universal
path: output-universal
retention-days: 14
Universal - Configuration file
Universal - Configuration file
{
"universal": {
"universal-example": {
"depends": null,
"sdk_url": "golang:latest",
"repo_path": "./",
"container_output_dirs": null,
"container_output_files": [
"test.txt"
],
"output_dir": "output-universal/",
"input_dirs": null,
"input_files": null,
"container_input_dir": "inputs/",
"build_commands": [
"echo 'hello world'",
"touch test.txt"
]
}
}
}