Skip to content

Commit b5edc26

Browse files
committed
Initial K-Boot support
K-Boot is a bootloader based on Linux kexec. The binary is generated from these projects: - linux (external project) - busybox (external project) - kexec-tools (external project) - kbootd K-Boot doesn't manage linux project neither provide the defconfig, the user take care of the linux project and must follow "Linux requirements" section from the README. busybox and kexec-tools project have been added as git submodules: - busybox: version 1.36.0 - kexec-tools: version 2.0.26 The reference HEAD will always point to the latest release. K-Boot daemon (kbootd) is executed by init and fulfilled these tasks: - read/write on MMC - read/list MMC partitions - read/write on USB (fastboot gadget) - support main fastboot commands (erase, flash, getvar, reboot ...) - multi-thread flashing (one thread read USB, one thread write MMC) - extract Boot Android partition: Kernel, ramdisk, dtb and cmdline Once we have extracted all Android components, kexec will boot on Android kernel. All the compilation is done through build scripts (build instructions in the README). In the future we will add the support for different SoC or linux distribution, most of the part are already generic. Signed-off-by: Julien Masson <[email protected]>
0 parents  commit b5edc26

34 files changed

+3188
-0
lines changed

.github/workflows/ci.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: CI
2+
3+
on: pull_request
4+
5+
jobs:
6+
lint:
7+
name: Lint
8+
runs-on: ubuntu-latest
9+
strategy:
10+
matrix:
11+
path:
12+
- 'kbootd'
13+
14+
steps:
15+
- uses: actions/checkout@v3
16+
- name: Run clang-format
17+
uses: jidicula/[email protected]
18+
with:
19+
clang-format-version: '13'
20+
check-path: ${{ matrix.path }}
21+
22+
build:
23+
name: Build
24+
runs-on: ubuntu-latest
25+
26+
steps:
27+
- name: Set up environment
28+
run: |
29+
sudo apt update
30+
sudo apt install meson
31+
32+
- uses: actions/checkout@v3
33+
with:
34+
submodules: 'true'
35+
36+
- name: Download musl toolchain
37+
run: |
38+
mkdir toolchain
39+
cd toolchain
40+
wget https://musl.cc/aarch64-linux-musl-cross.tgz
41+
tar zxvf aarch64-linux-musl-cross.tgz
42+
echo "$PWD/aarch64-linux-musl-cross/bin" >> $GITHUB_PATH
43+
44+
- name: Build busybox
45+
run: |
46+
./build/build_busybox.sh
47+
48+
- name: Build kexec
49+
run: |
50+
./build/build_kexec.sh
51+
52+
- name: Build kbootd
53+
run: |
54+
./build/build_kbootd.sh

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
initramfs/bin/busybox
2+
initramfs/bin/kbootd
3+
initramfs/bin/kexec
4+
k-boot-*.bin

.gitmodules

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[submodule "kexec-tools"]
2+
path = kexec-tools
3+
url = https://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git
4+
[submodule "busybox"]
5+
path = busybox
6+
url = https://git.busybox.net/busybox

README.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# K-Boot
2+
3+
K-Boot is a bootloader based on Linux kexec.
4+
5+
There is several benefits with this kind of bootloader solution:
6+
- no need to duplicate/integrate drivers from Kernel
7+
- no need to maintain another bootloader project
8+
- same kernel source code used between Linux and K-Boot
9+
- better boot/flashing performance
10+
- easier to extend or debug (many tools available)
11+
- use/contribute existing reliable projects
12+
13+
For now K-Boot target only `arm64` hardware.
14+
15+
### Setup environment
16+
17+
Fetch K-Boot project:
18+
``` console
19+
$ git clone --recurse-submodules [email protected]:baylibre/k-boot.git
20+
```
21+
22+
Download toolchains and add to `$PATH`:
23+
``` console
24+
# aarch64-linux-musl toolchain for userspace binaries
25+
$ wget https://musl.cc/aarch64-linux-musl-cross.tgz
26+
$ tar zxvf aarch64-linux-musl-cross.tgz
27+
28+
# aarch64-none-linux toolchain for linux
29+
$ wget https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz
30+
$ tar -xvf gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz
31+
```
32+
33+
### Linux requirements
34+
35+
K-Boot doesn't manage linux project neither provide the defconfig.
36+
37+
However the user must set in the defconfig:
38+
```
39+
CONFIG_INITRAMFS_SOURCE="usr/initramfs/setup"
40+
CONFIG_KEXEC=y
41+
```
42+
43+
### Build K-Boot
44+
45+
``` console
46+
$ ./build/build_all.sh --linux=~/src/linux --defconfig=kboot_defconfig
47+
```
48+
49+
All others build scripts can be run independently (`--help` for more infos).
50+
51+
### Intregration with Arm Trusted Firmware (ATF)
52+
53+
In the ARM boot flow, K-Boot will be used as `BL33`.
54+
55+
According to [Booting AArch64 Linux](https://docs.kernel.org/arm64/booting.html):
56+
> Primary CPU general-purpose register settings:
57+
> - x0 = physical address of device tree blob (dtb) in system RAM.
58+
59+
Thus the device tree must be loaded before booting to K-Boot and `x0` must be set to the physical address where the device tree has been loaded.
60+
61+
This task can be fulfilled by the `BL2`.
62+
63+
ATF Boot Flow example with K-Boot:
64+
1. MMC BOOT0 contains BL2 + Device Tree for K-Boot
65+
2. BL1 (ROM code) copy MMC BOOT0 to SRAM
66+
3. BL1 jump to SRAM and execute BL2
67+
4. BL2 initialize DDR, extract from fip image: BL31 (pm runtime services), BL32 (OP-TEE) and BL33 (K-Boot)
68+
5. BL2 copy the Device Tree for K-Boot found in SRAM to DDR and set x0 register
69+
6. BL2 jump to BL31
70+
7. BL31 boot and jump to OP-TEE
71+
8. OP-TEE boot and jump to K-Boot
72+
9. K-Boot kernel start, find init process in initramfs and execute K-Boot daemon (kbootd)
73+
74+
### Tips
75+
76+
Send `kbootd` over serial:
77+
``` console
78+
# On host
79+
$ sx kbootd < /dev/ttyUSB0 > /dev/ttyUSB0
80+
81+
# On device, make sure kbootd is not running
82+
# rx /bin/kbootd
83+
```
84+
85+
### Contributions
86+
87+
`kbootd` coding style:
88+
``` console
89+
$ clang-format -i kbootd/src/*
90+
```

build/build_all.sh

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/bin/bash
2+
3+
set -e
4+
set -u
5+
set -o pipefail
6+
7+
SRC=$(dirname "$(readlink -e "$0")")
8+
source "${SRC}/build_busybox.sh"
9+
source "${SRC}/build_kbootd.sh"
10+
source "${SRC}/build_kexec.sh"
11+
source "${SRC}/build_linux.sh"
12+
source "${SRC}/utils.sh"
13+
14+
function build_all {
15+
local clean="$1"
16+
local mode="$2"
17+
local linux="$3"
18+
local defconfig="$4"
19+
20+
build_busybox "${clean}" "${mode}"
21+
22+
build_kexec "${clean}" "${mode}"
23+
24+
build_kbootd "${clean}" "${mode}"
25+
26+
build_linux "$@"
27+
cp "${linux}/arch/arm64/boot/Image" "${ROOT}/k-boot-${mode}.bin"
28+
}
29+
30+
function usage {
31+
cat <<DELIM__
32+
usage: $(basename "$0") [options]
33+
34+
$ $(basename "$0") --linux=~/src/linux --defconfig=kboot_defconfig
35+
36+
Options:
37+
--linux Linux project path
38+
--defconfig Linux defconfig
39+
--clean (OPTIONAL) clean before build
40+
--mode (OPTIONAL) [release|debug|factory] mode (default: release)
41+
--help (OPTIONAL) display usage
42+
DELIM__
43+
}
44+
45+
function main {
46+
local script=$(basename "$0")
47+
local build="${script%.*}"
48+
local clean=false
49+
local defconfig=""
50+
local linux=""
51+
local mode="release"
52+
53+
local opts_args="clean,defconfig:,help,linux:,mode:"
54+
local opts=$(getopt -o '' -l "${opts_args}" -- "$@")
55+
eval set -- "${opts}"
56+
57+
while true; do
58+
case "$1" in
59+
--clean) clean=true; shift ;;
60+
--defconfig) defconfig="$2"; shift 2 ;;
61+
--linux) linux=$(find_path "$2"); shift 2 ;;
62+
--mode) mode="$2"; shift 2 ;;
63+
--help) usage; exit 0 ;;
64+
--) shift; break ;;
65+
esac
66+
done
67+
68+
# check arguments
69+
[ -z "${linux}" ] && error_usage_exit "Cannot find linux project"
70+
[ -z "${defconfig}" ] && error_usage_exit "defconfig not provided"
71+
! [[ " ${MODES[*]} " =~ " ${mode} " ]] && error_usage_exit "${mode} mode not supported"
72+
73+
# build
74+
build_all "${clean}" "${mode}" "${linux}" "${defconfig}"
75+
}
76+
77+
if [ "$0" = "$BASH_SOURCE" ]; then
78+
main "$@"
79+
fi

build/build_busybox.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/bin/bash
2+
3+
set -e
4+
set -u
5+
set -o pipefail
6+
7+
SRC=$(dirname "$(readlink -e "$0")")
8+
source "${SRC}/utils.sh"
9+
10+
BUSYBOX="${ROOT}/busybox"
11+
12+
function build_busybox {
13+
local clean="$1"
14+
local mode="$2"
15+
16+
display_current_build "busybox" "${mode}"
17+
18+
pushd "${BUSYBOX}"
19+
20+
export CROSS_COMPILE=aarch64-linux-musl-
21+
22+
[[ "${clean}" == true ]] && make clean
23+
24+
[ ! -f .config ] && make defconfig
25+
26+
make -j"$(nproc)" LDFLAGS="--static"
27+
28+
cp busybox "${INITRAMFS}/bin/"
29+
30+
unset CROSS_COMPILE
31+
32+
popd
33+
}
34+
35+
if [ "$0" = "$BASH_SOURCE" ]; then
36+
main "$@"
37+
fi

build/build_kbootd.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/bin/bash
2+
3+
set -e
4+
set -u
5+
set -o pipefail
6+
7+
SRC=$(dirname "$(readlink -e "$0")")
8+
source "${SRC}/utils.sh"
9+
10+
KBOOTD="${ROOT}/kbootd"
11+
12+
function build_kbootd {
13+
local clean="$1"
14+
local mode="$2"
15+
16+
display_current_build "kbootd" "${mode}"
17+
18+
pushd "${KBOOTD}"
19+
20+
export CROSS_COMPILE=aarch64-linux-musl-
21+
22+
[[ "${clean}" == true ]] && rm -rf build
23+
24+
if [ ! -d build ]; then
25+
meson setup build --prefix "${INITRAMFS}" --cross-file meson.cross
26+
fi
27+
28+
ninja -C build install
29+
30+
unset CROSS_COMPILE
31+
32+
popd
33+
}
34+
35+
if [ "$0" = "$BASH_SOURCE" ]; then
36+
main "$@"
37+
fi

build/build_kexec.sh

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/bin/bash
2+
3+
set -e
4+
set -u
5+
set -o pipefail
6+
7+
SRC=$(dirname "$(readlink -e "$0")")
8+
source "${SRC}/utils.sh"
9+
10+
KEXEC="${ROOT}/kexec-tools"
11+
12+
function build_kexec {
13+
local clean="$1"
14+
local mode="$2"
15+
16+
display_current_build "kexec" "${mode}"
17+
18+
pushd "${KEXEC}"
19+
20+
export CROSS_COMPILE=aarch64-linux-musl-
21+
22+
[[ "${clean}" == true ]] && make clean
23+
24+
[ ! -f configure ] && ./bootstrap
25+
26+
[ ! -f Makefile ] && LDFLAGS=-static ./configure --host=aarch64-linux-musl
27+
28+
make -j"$(nproc)"
29+
30+
aarch64-linux-musl-strip build/sbin/kexec
31+
cp build/sbin/kexec "${INITRAMFS}/bin/"
32+
33+
unset CROSS_COMPILE
34+
35+
popd
36+
}
37+
38+
if [ "$0" = "$BASH_SOURCE" ]; then
39+
main "$@"
40+
fi

0 commit comments

Comments
 (0)