Patching U-Boot
About 1803 wordsAbout 6 min
2026-03-23
Overview
Patches in U-Boot are used to:
- Add support for a custom board/SoC not yet upstream
- Apply bug fixes between releases
- Backport features from newer U-Boot to a stable tag
- Apply vendor-specific modifications (NDA code, proprietary drivers)
- Prepare patches for upstream submission
U-Boot uses standard Linux kernel patch workflow: patches in unified diff format (git format-patch) applied via git am or patch.
Patch Management Approaches
Approach 1: Git Commits on a Branch (Recommended for BSP Development)
v2026.01 tag (upstream)
|
├── commit: "arm: mysoc: add MySoC SoC support"
├── commit: "board: myvendor: add myboard support"
├── commit: "configs: add myboard_defconfig"
└── commit: "arm: dts: add mysoc-myboard device tree"This is the cleanest approach: your patches live as normal git commits on a feature branch.
# Start from the tag
git checkout -b feature/myboard v2026.01
# Make changes and commit them
git add arch/arm/mach-mysoc/
git commit -m "arm: mysoc: add MySoC SoC clock driver"
git add board/myvendor/myboard/
git commit -m "board: myvendor/myboard: add initial board support"Approach 2: Quilt (for patchset management)
Quilt is a classic patch management tool used when you manage patches as files. Widely used in Yocto BSP layers and OpenEmbedded.
sudo apt-get install quiltApproach 3: Yocto .bbappend patches
If building U-Boot via Yocto/OE, patches are placed in the recipe's files/ directory and applied via SRC_URI. (Covered separately in the Yocto section.)
Method 1: Git-Based Patch Workflow
Creating Patches with git format-patch
git format-patch creates .patch files from commits. Each file is a complete, self-contained patch with metadata.
# Generate patch for the last commit
git format-patch -1 HEAD
# Generate patches for last 3 commits
git format-patch -3 HEAD
# Generate patches from a range
git format-patch v2026.01..HEAD
# Generate patches into a specific directory
git format-patch -o /tmp/myboard-patches v2026.01..HEAD
# Generate a numbered patch series (001-..., 002-..., etc.)
git format-patch --numbered v2026.01..HEAD -o patches/
# Add a cover letter (patch series summary email)
git format-patch --cover-letter -n v2026.01..HEAD -o patches/
# Edit patches/0000-cover-letter.patch with subject and descriptionPatch File Format
A patch file produced by git format-patch looks like:
From a1b2c3d4e5f6... Mon Sep 17 00:00:00 2001
From: Your Name <your.email@company.com>
Date: Mon, 23 Mar 2026 10:00:00 +0000
Subject: [PATCH 1/3] board: myvendor/myboard: add initial board support
Add support for MyBoard based on MySoC Cortex-A55.
Key features:
- 1 GB LPDDR4 at 0x40000000
- eMMC HS400 on USDHC1
- Designware Ethernet
- NS16550 UART console
Signed-off-by: Your Name <your.email@company.com>
---
board/myvendor/myboard/Kconfig | 20 +++
board/myvendor/myboard/Makefile | 5 +
board/myvendor/myboard/myboard.c | 180 +++++++++++++++++++++++
configs/myboard_defconfig | 55 +++++++
4 files changed, 260 insertions(+)
create mode 100644 board/myvendor/myboard/Kconfig
...
diff --git a/board/myvendor/myboard/Kconfig b/board/myvendor/myboard/Kconfig
new file mode 100644
index 000000000000..b1c2d3e4f5a6
--- /dev/null
+++ b/board/myvendor/myboard/Kconfig
@@ -0,0 +1,20 @@
+if TARGET_MYBOARD
+
+config SYS_BOARD
+ default "myboard"
...Applying Patches with git am
# Apply a single patch
git am 0001-board-myvendor-myboard-add-initial-board-support.patch
# Apply all patches in a directory
git am patches/*.patch
# Apply patches with 3-way merge (helps with conflicts)
git am -3 patches/*.patch
# Apply patches while keeping message-ID for reference
git am --keep-cr patches/*.patch
# If a patch fails to apply cleanly:
git am --abort # Abort and reset to pre-am state
git am --skip # Skip the failing patch (dangerous! may lose changes)
# After manually resolving conflicts:
git add <conflicted-files>
git am --continueApplying Patches with the patch Tool
For simple patches not in git format:
# Apply from file
patch -p1 < mypatch.patch
# Test without applying (dry run)
patch -p1 --dry-run < mypatch.patch
# Reverse/undo a patch
patch -p1 -R < mypatch.patch
# Handle CRLF line endings
patch -p1 --binary < mypatch.patchMethod 2: Quilt Patch Series Management
Quilt manages a stack of patches on top of a base source tree. Patches are stored as files in a patches/ directory with a series file controlling order.
Setting Up Quilt
# Install quilt
sudo apt-get install quilt
# Configure quilt (create ~/.quiltrc)
cat > ~/.quiltrc << 'EOF'
QUILT_DIFF_ARGS="--no-timestamps --no-index -p ab --color=auto"
QUILT_REFRESH_ARGS="--no-timestamps --no-index -p ab"
QUILT_SERIES_ARGS="--color=auto"
QUILT_PATCH_OPTS="--unified"
QUILT_DIFF_OPTS="-p"
EDITOR=vim
EOFInitial Setup on U-Boot Source
cd u-boot
# Initialize quilt on the source (non-git, or alongside git)
# quilt uses patches/ directory and patches/series file
ls patches/ # Will be created when you push first patch
cat patches/series # Ordered list of patches to applyCreating a New Patch with Quilt
# Import quilt
export QUILT_PATCHES=patches # Default, can omit
# Create a new empty patch
quilt new 0001-board-myvendor-myboard-initial.patch
# Add files that the patch will modify
quilt add board/myvendor/myboard/myboard.c
quilt add configs/myboard_defconfig
quilt add arch/arm/dts/mysoc-myboard.dts
# ... make your edits to those files ...
vim board/myvendor/myboard/myboard.c
# Refresh (finalize) the patch
quilt refresh
# Check the patch contents
quilt diff # Show uncommitted changes vs top patch
quilt top # Show currently active top patchWorking with the Patch Stack
# Show all patches in series
quilt series
# Show which patches are applied
quilt applied
# Show which patches are not yet applied
quilt unapplied
# Push (apply) next patch
quilt push
# Push all patches
quilt push -a
# Pop (unapply) top patch
quilt pop
# Pop all patches
quilt pop -a
# Go to a specific patch
quilt goto 0003-drivers-net-add-myeth.patch
# Edit a patch that's already in the stack
quilt push -a # Apply all
quilt goto 0002-some-patch.patch # Go to the patch
quilt add drivers/net/myeth.c # Add new file to patch scope
# ... edit the file ...
quilt refresh # Update the patch file
quilt pop -a # Pop all
quilt push -a # Re-apply cleanlyThe patches/series File
# patches/series
0001-arm-mysoc-add-clock-driver.patch
0002-arm-mysoc-add-ddr-init.patch
0003-board-myvendor-myboard-initial-support.patch
0004-configs-add-myboard-defconfig.patch
0005-arm-dts-add-mysoc-myboard.patch
0006-drivers-net-dwmac-fix-speed-negotiation.patch -p1The optional -p1 after a patch name overrides the default strip level.
Method 3: Applying Vendor / Third-Party Patches
Typical Vendor SDK Patch Structure
Vendors (NXP, Rockchip, TI, etc.) often provide U-Boot forks or patch series:
# Example: NXP i.MX releases patches relative to U-Boot tag
# NXP release: lf-6.6.52-2.2.0 uses u-boot-lf_v2024.04
git clone https://github.com/nxp-imx/uboot-imx.git
git checkout lf_v2024.04
# Their commits are additional patches on top of v2024.04
git log v2024.04..HEAD --oneline | head -20Extracting Vendor Patches
If you want to apply vendor patches onto a different base (e.g., to maintain alignment with v2026.01):
# Generate patches from vendor commits on top of base tag
cd uboot-vendor
git format-patch v2026.01..HEAD -o /tmp/vendor-patches/
# Apply to your clean v2026.01 tree
cd u-boot
git am --reject -3 /tmp/vendor-patches/*.patch
# Review rejects manually
find . -name "*.rej" | xargs ls -laHandling Patch Conflicts
# When git am fails, view the failure
git am --show-current-patch
# Option 1: Edit the file, mark resolved, continue
vim drivers/mmc/sdhci.c # Fix conflict manually
git add drivers/mmc/sdhci.c
git am --continue
# Option 2: Use git mergetool
git mergetool
# Option 3: Abort and redo with 3-way merge
git am --abort
git am -3 0042-drivers-mmc-sdhci-fix-timing.patchUsing U-Boot's patman Tool
patman is U-Boot's own patch preparation and submission tool. It automates tagging, CC lists, version tracking, and formatting patches for submission.
Setup
# Install patman dependencies
pip3 install gitpython pygit2
# Configure patman (reads from .patman in repo root or ~/.patman)
cat > .patman << 'EOF'
[settings]
smtp_server: smtp.gmail.com
smtp_port: 587
from_address: yourname@company.com
[alias]
u-boot: u-boot@lists.denx.de
tom: Tom Rini <trini@konsulko.com>
EOF
# Add maintainer database (from .mailmap / MAINTAINERS-like file)Creating a Patch Series with patman
# From your branch with commits
# patman reads commit messages for tags like:
# Series-to: u-boot
# Series-cc: tom
# Cover-letter: END
# ... description ...
# END
# Create series
tools/patman/patman.py send --dry-run -n 5 # Last 5 commits
tools/patman/patman.py send -n 5 # Actually send to mailing listCommit Message Format for patman
board: myvendor/myboard: add initial board support
Add support for MyBoard based on MySoC Cortex-A55 platform.
The board features:
- 1 GB LPDDR4 at 0x40000000
- eMMC 5.1 HS400 on USDHC1
- Designware GMAC Ethernet
- NS16550 UART
Series-to: u-boot
Series-cc: Heinrich Schuchardt <xypron.glx@gmx.de>
Reviewed-by: Tom Rini <trini@konsulko.com>
Signed-off-by: Your Name <your.email@company.com>Applying Patches in Yocto (for BSP integration)
When integrating U-Boot into a Yocto build via a BSP layer, patches go in the recipe's files/ or patches/ directory:
Directory Structure
meta-myvendor/
└── recipes-bsp/
└── u-boot/
├── u-boot-myvendor_2026.01.bb (or .bbappend)
└── files/
├── 0001-arm-mysoc-add-clocks.patch
├── 0002-board-myvendor-add-myboard.patch
├── 0003-configs-add-myboard-defconfig.patch
└── myboard_defconfigu-boot-myvendor_2026.01.bb
# recipes-bsp/u-boot/u-boot-myvendor_2026.01.bb
DESCRIPTION = "U-Boot bootloader for MyVendor boards"
LICENSE = "GPL-2.0-or-later"
LIC_FILES_CHKSUM = "file://Licenses/gpl-2.0.txt;md5=b234ee4d..."
# Inherit the standard U-Boot class
inherit uboot-config
# Source: U-Boot v2026.01 + patches
SRC_URI = "git://source.denx.de/u-boot/u-boot.git;branch=master;protocol=https \
file://0001-arm-mysoc-add-clocks.patch \
file://0002-board-myvendor-add-myboard.patch \
file://0003-configs-add-myboard-defconfig.patch \
file://myboard_defconfig \
"
SRCREV = "abcdef1234567890abcdef1234567890abcdef12" # Commit for v2026.01
PV = "2026.01+git${SRCPV}"
S = "${WORKDIR}/git"
# defconfig to use for this machine
UBOOT_CONFIG ??= "myboard"
UBOOT_CONFIG[myboard] = "myboard_defconfig,,u-boot.itb"
# Build SPL + proper
UBOOT_MAKE_TARGET = "all"
UBOOT_BINARY = "u-boot.itb"
SPL_BINARY = "spl/u-boot-spl.bin".bbappend Approach (Extending Existing Recipe)
# recipes-bsp/u-boot/u-boot_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI:append:myboard = " \
file://0001-arm-mysoc-add-clocks.patch \
file://0002-board-myvendor-add-myboard.patch \
file://0003-configs-add-myboard-defconfig.patch \
"
UBOOT_MACHINE:myboard = "myboard_defconfig"Patch Checkpatch Validation
Before submitting patches upstream, always run checkpatch.pl:
# Check a single patch file
scripts/checkpatch.pl 0001-board-myvendor-myboard-initial.patch
# Check the last N commits
scripts/checkpatch.pl --git HEAD~3..HEAD
# Check a specific file for style
scripts/checkpatch.pl --no-tree -f board/myvendor/myboard/myboard.c
# Check with relaxed rules (for board-specific code)
scripts/checkpatch.pl --subjective 0001-*.patchCommon issues found by checkpatch:
- Missing
SPDX-License-Identifierheader - Lines longer than 80 characters (U-Boot limit)
- Trailing whitespace
- Missing
Signed-off-by:line - Wrong commit message format
- Function declarations with arguments in wrong style
- Use of banned functions (
strcpy,sprintfwithout bounds check)
Maintaining a Patch Series Across U-Boot Versions
Rebasing Patches to a New Release
# You are on: feature/myboard based on v2025.10
# You want to: rebase onto v2026.01
git fetch origin
git checkout feature/myboard
# Rebase all your commits onto the new tag
git rebase --onto v2026.01 v2025.10 feature/myboard
# Resolve any conflicts
# Run: git status → edit conflicted files → git add → git rebase --continue
# Verify build still works
make myboard_defconfig && make -j$(nproc)Using buildman to Test Patch Impact
# Build the board before and after the patch
tools/buildman/buildman.py -o /tmp/before myboard
git am mypatch.patch
tools/buildman/buildman.py -o /tmp/after myboard
# Compare binary sizes
ls -la /tmp/before/myboard/u-boot.bin /tmp/after/myboard/u-boot.bin