Getting Started
Install dependencies
Debian 12 / Ubuntu 22.04
sudo apt update
sudo apt install -y git qemu-user-static binfmt-support
# Podman (recommended)
sudo apt install -y podman podman-docker
sudo touch /etc/containers/nodocker
# Docker
#sudo apt install docker.io
# Optional dependcies for minor features
sudo apt install -y systemd-container
Check out the code
bsp
uses git submodules. As such, please check out the code with the following command:
git clone --recurse-submodules https://github.com/radxa-repo/bsp.git
Understand bsp
's usage
Once the repo is cloned on your machine, you can run bsp
to check the built-in help:
The built-in help is intended as the first step to troubleshoot for bsp
usage,
while the documentation site covers more about high level applications and low level
implementation details. As such, you are more likely to find your questions solved
by an option listed in the built-in help.
It is strongly recommended to read the built-in help at once, if you want to do anything beyond the trival package rebuild.
cd bsp
./bsp
Build your first packages
bsp
now supports building kernel and U-Boot in a single step, and specify them
by product name instead of specific profiles. This should help new users to test
their setup without much bsp
knowledge:
# The following command will build linux-stable
# and u-boot-latest for radxa-zero
./bsp radxa-zero
Custom kernel/firmware developer should at least read the Development reference
section to better understand the development workflow and the internal data
sctructure for bsp
.
Local development workflow
In this article, we will demonstrate how to develop and create patches for bsp
.
Prepare working tree
Use --no-build
and -C|--distclean
to set up the source tree with bsp
predefined profiles:
./bsp -C --no-build linux latest
Retrive additional commit history
bsp
uses shallow clone by default to save bandwidth and speed up build process.
However, you might want to access additional git history for rebase
or cherry-pick
.
You can use either of the following 2 options to fetch more commits:
cd .src/linux
# Fetch HEAD~10 commits
git fetch --depth=10 --all
# Fetch everything
# WARNING! VERY SLOW!
git fetch --unshallow --all
Build packages
You can use --dirty
to build without resetting the source tree. This will allow the build process to reuse previously built objects:
./bsp --dirty linux latest
Install build artifacts
You can use ./bsp install
to install the built package to a root partition (like a microSD card):
./bsp install linux-image-6.*_arm64.deb /dev/sdb2
Create patch set
After you are happy with the changes, you can export your commits with git format-patch
:
mkdir -p linux/latest/0500-my-first-pr
cd .src/linux
# Update start-number to the last one + 1
# in your targetting patch subfolder
git format-patch -M -N --start-number 1 --zero-commit -o ../../linux/latest/0500-my-first-pr HEAD~1
Move the outputted patch files to the corresponding subfolder, and you are ready to submit your first PR!
Developer FAQ
bsp
takes a lot of time applying patches
There are 2 possible causes:
- Your
bsp
project is stored on mechinical hard drives.
As patching is random 4K intensive, we suggest you putbsp
on solid state drives. - Your source tree has too many dangling commits.
This happens naturally as you use the project. You can go to the source tree under.src
and rungit gc --prune
to restore the performance.
Understand profile
Profiles are subfolders under linux
and u-boot
folder. Each of them describes a specific flavor of their targeted software.
Special files
- fork.conf: Profile config file
- kconfig.conf: kconfig overriding file
Tree structure and mode of operation
sample
├── 0001-common -> ../.common/
├── 0010-backport
│ ├── 0001-scripts-dtc-Update-to-upstream-version-v1.6.0-51-g18.patch
│ ├── 0002-kbuild-Add-support-to-build-overlays-.dtbo.patch.ignore
│ ├── 0003-mm-page_alloc-fix-building-error-on-Werror-array-com.patch
│ └── 0004-etherdevice-Adjust-ether_addr-prototypes-to-silence-.patch
├── 0001-Fix-multiple-definition-of-yylloc.patch
├── 0002-Suppress-additional-warnings.patch
├── fork.conf
├── kconfig.conf
└── rockchip -> ../.rockchip
fork.conf
fork.conf
is the profile configuration file. This file is mandatory and is sourced early by bsp
.
BSP_GIT
defines upstream source repo.
BSP_COMMIT
or BSP_BRANCH
or BSP_TAG
defines the exact source code. The first defined option in the listed order will be used.
BSP_DEFCONFIG
defines the defconfig used for building. Default to defconfig
.
SUPPORTED_BOARDS
defines the supported product list, which is a Bash array. bsp
will use this list to create metapackages that reference the binary package. Suffixes are commonly used to denote kernel/firmware variants that also support the same board. However, the default package is the one that matches exactly to the product name.
You can read more about SUPPORTED_BOARDS
in Build artifacts section.
kconfig.conf
kconfig.conf
is a kernel configuration file. This file mirrors defconfig
format.
Build artifacts
Every time bsp
completes a build, it will create at least 2 packages. We will discuss what they are in this article.
linux-rockchip
5.10.110-5 release will be used as an example.
Specifically, we will focus on the following 3 packages:
File Name | Size |
---|---|
linux-headers-5.10.110-5-rockchip_5.10.110-5-1932709cf_arm64.deb | 7.4 MB |
linux-headers-radxa-nx5-io_5.10.110-5-3a557f6_all.deb | 1.1 KB |
... | ... |
linux-headers-rockchip_5.10.110-5-3a557f6_all.deb | 1.08 KB |
Debian package naming convention
Generall, Debian packages are named in the following format:
PACKAGE-NAME _ PACKAGE-VERSION _ PACKAGE-ARCHITCTURE .deb
The three components are seperated by the underscore.
Binary package
Binary package is the artifacts generated by the related source code.
They are large because they contain the real code.
In the above list linux-headers-5.10.110-5-rockchip
is the real package.
For kernel related package, we additionally adds part of the package version to the package name, which is why you see 5.10.110-5
repeated in the package name above. The advantage of this is that now different versions of kernel are actually different packages (remember they are identified by the package name). This allows us to install different kernels at the same time, and the user can decided which one to boot at run time.
For firmware package, we only allow a single package to be installed (i.e. no version in the name). This is because firmware has to be installed in a fixed place, so it is not possible to switch between them.
In above list you also see 1932709cf
is included in the package version. This is the base commit ID in case the related bsp
profile is defined with a Git branch. This way we can determine which exact commit was used at the time of building.
Metapackages
One issue introduced by having a unique name for each kernel package is that now it is very hard to track which kernel supports what products, and there is no automatic upgrade since each new version is an entire new package.
To solve this problem, metapackages are built by bsp
along with the binary package.
The list of metapackages is based on SUPPORTED_BOARDS
defined in fork.conf
. The purposes for them are:
- They reference the latest binary package as their dependency.
- Since they do not have a unique name per release, they can be updated, which will automatically pulls the new binary package as the dependency.
- They also have a consistent name, so this makes tracking kernel with product a non-issue.
Beyond the supported products defined in SUPPORTED_BOARDS
, we also define the profile name as a metapackage. This allows the user to install a specific profile of kernel/firmware instead of worrying about product updates it's source code dependencies.
Metapackages are usually very small since they only need to reference the binary package, and contains no code.
In above list you also see 3a557f6
is included in the package version. Since they are created entirely by bsp
, this is the bsp
commit used at the build time.
Firmware management
Firmware, or do you mean U-Boot?
bsp
is intended to be a general Board Support Package builder. In this sense,
there are firmwares which perform low level initialization, and kernel which
runs the operating system. Currently the only kernel bsp
supports is Linux, and
the only supported firmware is U-Boot. However, we plan to support EDK2 in the
future, thus this section is titled firmware management.
U-Boot installation location
Following Debian convention, we install U-Boot under /usr/lib/u-boot
folder,
and save all supported bootloaders in a single package.
We also provide a maintenance script called setup.sh
.
Extracting binaries from released package
Firmware binaries are usually needed to perform various offline recovery tasks. As we only release firmware in the form of Debian package, it is necessary to extract the required files first before performing any recovery steps.
On Windows, you can extract .deb
files with 7-Zip.
On Linux, you can run following command to extrace the package:
ar p u-boot-latest.deb data.tar.xz | tar -xJ
setup.sh
usage
Under each board's directory, there are a few binary blobs, along with a maintenance script called setup.sh
, which provides a wrapper for common management tasks.
There is minimal error checking in the script, as such, it is intended as the advanced method of bootloader management. Normal user should use rsetup
instead, which provides a TUI for bootloader update.
Additionally, not all commands are intended for the end user usage. Below are documented and supported commands:
Common setup.sh
command
setup.sh maskrom
Maskrom is a special boot mode, that can run binary passed via USB OTG connection. This is usually the first command to run when you boot the board in maskrom mode.
For Amlogic devices, the binary is actually a normal U-Boot binary running in memory, so you can access the U-Boot console for recovery.
For Rockchip devices, the binary allows access to on-board eMMC via rkdeveloptool
.
setup.sh update_bootloader <file>
This command update the installed bootloader on a uncompressed system image file. Since block devices is also a file, the command can also update the bootloader on storage medias like eMMC or NVMe SSD.
Rockchip specific setup.sh
command
setup.sh maskrom_autoupdate_bootloader
This command update the eMMC bootloader via Rockchip Maskrom mode. You do not need to run setup.sh maskrom
first when using this command.
setup.sh maskrom_autoupdate_spinor
This command update the SPI bootloader via Rockchip Maskrom mode. You do not need to run setup.sh maskrom
first when using this command.
setup.sh update_spinor [mtd_device]
This command update the installed bootloader on the SPI flash. When no mtd_device
is assigned, it will update /dev/mtd0
.
Update firmware
Download and extract prebuilt firmware
If you do not want to build the firmware from source, you can also use our prebuilt firmwares.
Please first go to their latest release and find your product in the asset list:
Example release from https://github.com/radxa-pkg/u-boot-latest/releases/latest
You should then download the binary package from the supported release. In our example we will use u-boot-latest_2023.07.02-6-4257d241_arm64.deb
as an example.
If you don't know what is binary package, please read Build artifacts section.
mkdir extract
cd extract
wget https://github.com/radxa-pkg/u-boot-latest/releases/download/2023.07.02-6/u-boot-latest_2023.07.02-6-4257d241_arm64.deb
ar vx *.deb
tar xvf data.tar.xz
ls usr/lib/u-boot/
You should see output similar to this:
[excalibur@yuntian extract]$ ls usr/lib/u-boot/
radxa-cm3-io radxa-e23 radxa-zero rock-3a rock-4-core-io rock-pi-4a rock-pi-4b-plus rock-pi-s
radxa-cm3-rpi-cm4-io radxa-e25 radxa-zero-2pro rock-3b rock-4c-plus rock-pi-4a-plus rock-pi-4c
radxa-cm3-sodimm-io radxa-e61 radxa-zero3 rock-3c rock-4se rock-pi-4b rock-pi-n10
This means the firmware is extracted and is ready to use.
Update firmware existing system
To install the firmware to an existing system image (must be uncompressed raw image), or a block device (ex. microSD card), you can use the included setup.sh
. With ROCK 4SE as an example:
sudo usr/lib/u-boot/rock-4se/setup.sh update_bootloader ~/system.img # Update a system image
# OR
sudo usr/lib/u-boot/rock-4se/setup.sh update_bootloader /dev/sdX # Update a block device
You can read more abour setup.sh
from its own page.
Running from GitHub Workflows
Please check out our GitHub workflows as an example.
Reproduce a previous release
In this example, we will recreate linux-rockchip
5.10.110-5 release.
-
Follow Build artifacts section, We now have the following essential commit information at the release build time:
radxa/kernel
:1932709cf
bsp
:3a557f6
-
However,
fork.conf
only takes full commit hash. So click theradxa/kernel
link above, and clickBrowse files
button on GitHub page, that will get you the full commit hash in the URL bar:radxa/kernel
:1932709cf7d98d0d92952bba38d990d938fabc58
-
We can also check the content of
overlay.sh
to find the commit used forradxa/overlays
:
radxa/overlays
:4940ae33e4def0fb9133faf68adf0c3421b61f06
-
We can now recreate the package:
git clone --recurse-submodules https://github.com/radxa-repo/bsp.git
cd bsp
# switch to bsp commit found above
git switch --detach 3a557f6
# replace BSP_BRANCH with radxa/kernel commit found above
sed -i "s/BSP_BRANCH.*/BSP_COMMIT='1932709cf7d98d0d92952bba38d990d938fabc58'/" linux/rockchip/fork.conf
./bsp linux rockchip
# the prepared kernel tree will be available under .src/linux