/
build-kernel.sh
executable file
·343 lines (282 loc) · 8.94 KB
/
build-kernel.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
#!/bin/bash
#
# Copyright (c) 2018 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
description="
Description: This script is the *ONLY* to build a kernel for development.
"
set -o errexit
set -o nounset
set -o pipefail
readonly script_name="$(basename "${BASH_SOURCE[0]}")"
readonly script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
#project_name
readonly project_name="kata-containers"
[ -n "${GOPATH:-}" ] || GOPATH="${HOME}/go"
# Fetch the first element from GOPATH as working directory
# as go get only works against the first item in the GOPATH
GOPATH="${GOPATH%%:*}"
# Kernel version to be used
kernel_version=""
# Flag know if need to download the kernel source
download_kernel=false
# The repository where kernel configuration lives
runtime_repository="github.com/${project_name}/runtime"
# The repository where kernel configuration lives
readonly kernel_config_repo="github.com/${project_name}/packaging"
readonly patches_repo="github.com/${project_name}/packaging"
readonly patches_repo_dir="${GOPATH}/src/${patches_repo}"
# Default path to search patches to apply to kernel
readonly default_patches_dir="${patches_repo_dir}/kernel/patches/"
# Default path to search config for kata
readonly default_kernel_config_dir="${GOPATH}/src/${kernel_config_repo}/kernel/configs"
#Path to kernel directory
kernel_path=""
#
patches_path=""
#
hypervisor_target=""
#
arch_target=""
#
kernel_config_path=""
# destdir
DESTDIR="${DESTDIR:-/}"
#PREFIX=
PREFIX="${PREFIX:-/usr}"
source "${script_dir}/../scripts/lib.sh"
usage() {
cat <<EOT
Overview:
Build a kernel for Kata Containers
${description}
Usage:
$script_name [options] <command> <argument>
Commands:
- setup
- build
- install
Options:
-c <path>: Path to config file to build a the kernel
-h : Display this help.
-k <path>: Path to kernel to build
-p <path>: Path to a directory with patches to apply to kernel.
-v : Kernel version to use if kernel path not provided.
EOT
}
# Convert architecture to the name used by the Linux kernel build system
arch_to_kernel() {
local -r arch="$1"
case "$arch" in
aarch64) echo "arm64" ;;
ppc64le) echo "powerpc" ;;
x86_64) echo "$arch" ;;
s390x) echo "s390" ;;
*) die "unsupported architecture: $arch" ;;
esac
}
get_kernel() {
local version="${1:-}"
#Remove extra 'v'
version=${version#v}
local kernel_path=${2:-}
[ -n "${kernel_path}" ] || die "kernel_path not provided"
[ ! -d "${kernel_path}" ] || die "kernel_path already exist"
major_version=$(echo "${version}" | cut -d. -f1)
kernel_tarball="linux-${version}.tar.xz"
curl --fail -OL "https://cdn.kernel.org/pub/linux/kernel/v${major_version}.x/sha256sums.asc"
grep "${kernel_tarball}" sha256sums.asc >"${kernel_tarball}.sha256"
if [ -f "${kernel_tarball}" ] && ! sha256sum -c "${kernel_tarball}.sha256"; then
info "invalid kernel tarball ${kernel_tarball} removing "
rm -f "${kernel_tarball}"
fi
if [ ! -f "${kernel_tarball}" ]; then
info "Download kernel version ${version}"
info "Download kernel"
curl --fail -OL "https://www.kernel.org/pub/linux/kernel/v${major_version}.x/${kernel_tarball}"
else
info "kernel tarball already downloaded"
fi
sha256sum -c "${kernel_tarball}.sha256"
tar xf "${kernel_tarball}"
mv "linux-${version}" "${kernel_path}"
}
get_major_kernel_version() {
local version="${1}"
[ -n "${version}" ] || die "kernel version not provided"
major_version=$(echo "${version}" | cut -d. -f1)
minor_version=$(echo "${version}" | cut -d. -f2)
echo "${major_version}.${minor_version}"
}
get_default_kernel_config() {
local version="${1}"
local hypervisor="$2"
local kernel_arch="$3"
[ -n "${version}" ] || die "kernel version not provided"
[ -n "${hypervisor}" ] || die "hypervisor not provided"
[ -n "${kernel_arch}" ] || die "kernel arch not provided"
local kernel_ver
kernel_ver=$(get_major_kernel_version "${version}")
config="${default_kernel_config_dir}/${kernel_arch}_kata_${hypervisor}_${major_kernel}.x"
[ -f "${config}" ] || die "failed to find default config ${config}"
echo "${config}"
}
get_config_and_patches() {
if [ -z "${patches_path}" ]; then
info "Clone config and patches"
patches_path="${default_patches_dir}"
[ -d "${patches_path}" ] || git clone "https://${patches_repo}.git" "${patches_repo_dir}"
fi
}
get_config_version() {
get_config_and_patches
config_version_file="${default_patches_dir}/../kata_config_version"
if [ -f "${config_version_file}" ]; then
cat "${config_version_file}"
else
die "failed to find ${config_version_file}"
fi
}
setup_kernel() {
local kernel_path=${1:-}
[ -n "${kernel_path}" ] || die "kernel_path not provided"
if [ -d "$kernel_path" ]; then
info "${kernel_path} already exist"
return
fi
info "kernel path does not exist, will download kernel"
download_kernel="true"
[ -n "$kernel_version" ] || die "failed to get kernel version: Kernel version is emtpy"
if [[ ${download_kernel} == "true" ]]; then
get_kernel "${kernel_version}" "${kernel_path}"
fi
[ -n "$kernel_path" ] || die "failed to find kernel source path"
get_config_and_patches
[ -d "${patches_path}" ] || die " patches path '${patches_path}' does not exist"
local major_kernel
major_kernel=$(get_major_kernel_version "${kernel_version}")
local patches_dir_for_version="${patches_path}/${major_kernel}.x"
local kernel_patches=""
if [ -d "${patches_dir_for_version}" ]; then
kernel_patches=$(find "${patches_dir_for_version}" -name '*.patch' -type f)
else
info "kernel patches directory does not exit"
fi
[ -n "${arch_target}" ] || arch_target="$(uname -m)"
arch_target=$(arch_to_kernel "${arch_target}")
(
cd "${kernel_path}" || exit 1
for p in ${kernel_patches}; do
info "Applying patch $p"
patch -p1 --fuzz 0 <"$p"
done
[ -n "${hypervisor_target}" ] || hypervisor_target="kvm"
[ -n "${kernel_config_path}" ] || kernel_config_path=$(get_default_kernel_config "${kernel_version}" "${hypervisor_target}" "${arch_target}")
cp "${kernel_config_path}" ./.config
make oldconfig
)
}
build_kernel() {
local kernel_path=${1:-}
[ -n "${kernel_path}" ] || die "kernel_path not provided"
[ -d "${kernel_path}" ] || die "path to kernel does not exist, use ${script_name} setup"
[ -n "${arch_target}" ] || arch_target="$(uname -m)"
arch_target=$(arch_to_kernel "${arch_target}")
pushd "${kernel_path}" >>/dev/null
make -j $(nproc) ARCH="${arch_target}"
[ "$arch_target" != "powerpc" ] && ([ -e "arch/${arch_target}/boot/bzImage" ] || [ -e "arch/${arch_target}/boot/Image.gz" ])
[ -e "vmlinux" ]
popd >>/dev/null
}
install_kata() {
local kernel_path=${1:-}
[ -n "${kernel_path}" ] || die "kernel_path not provided"
[ -d "${kernel_path}" ] || die "path to kernel does not exist, use ${script_name} setup"
pushd "${kernel_path}" >>/dev/null
config_version=$(get_config_version)
[ -n "${config_version}" ] || die "failed to get config version"
install_path=$(readlink -m "${DESTDIR}/${PREFIX}/share/${project_name}")
vmlinuz="vmlinuz-${kernel_version}-${config_version}"
vmlinux="vmlinux-${kernel_version}-${config_version}"
if [ -e "arch/${arch_target}/boot/bzImage" ]; then
bzImage="arch/${arch_target}/boot/bzImage"
elif [ -e "arch/${arch_target}/boot/Image.gz" ]; then
bzImage="arch/${arch_target}/boot/Image.gz"
elif [ "${arch_target}" != "powerpc" ]; then
die "failed to find image"
fi
if [ "${arch_target}" = "powerpc" ]; then
install --mode 0644 -D "vmlinux" "${install_path}/${vmlinuz}"
else
install --mode 0644 -D "${bzImage}" "${install_path}/${vmlinuz}"
fi
install --mode 0644 -D "vmlinux" "${install_path}/${vmlinux}"
install --mode 0644 -D ./.config "${install_path}/config-${kernel_version}"
ln -sf "${vmlinuz}" "${install_path}/vmlinuz.container"
ln -sf "${vmlinux}" "${install_path}/vmlinux.container"
ls -la "${install_path}/vmlinux.container"
ls -la "${install_path}/vmlinuz.container"
popd >>/dev/null
}
main() {
while getopts "a:c:hk:p:t:v:" opt; do
case "$opt" in
a)
arch_target="${OPTARG}"
;;
c)
kernel_config_path="${OPTARG}"
;;
h)
usage
exit 0
;;
k)
kernel_path="${OPTARG}"
;;
t)
hypervisor_target="${OPTARG}"
;;
p)
patches_path="${OPTARG}"
;;
v)
kernel_version="${OPTARG}"
;;
esac
done
shift $((OPTIND - 1))
subcmd="${1:-}"
[ -z "${subcmd}" ] && usage 1
# If not kernel version take it from versions.yaml
if [ -z "$kernel_version" ]; then
kernel_version=$(get_from_kata_deps "assets.kernel.version")
#Remove extra 'v'
kernel_version="${kernel_version#v}"
fi
if [ -z "${kernel_path}" ]; then
config_version=$(get_config_version)
kernel_path="${PWD}/kata-linux-${kernel_version}-${config_version}"
info "Config version: ${config_version}"
fi
info "Kernel version: ${kernel_version}"
case "${subcmd}" in
build)
build_kernel "${kernel_path}"
;;
install)
build_kernel "${kernel_path}"
install_kata "${kernel_path}"
;;
setup)
setup_kernel "${kernel_path}"
[ -d "${kernel_path}" ] || die "${kernel_path} does not exist"
echo "Kernel source ready: ${kernel_path} "
;;
*)
usage 1
;;
esac
}
main $@