summaryrefslogtreecommitdiffstats
path: root/core/modules/kernel-vanilla/module.build
blob: ec40e6490f7abcb3c579a50b13ecee41f4708ed4 (plain) (blame)
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
#!/bin/bash
# Customized kernel from system: fetch Distro's kernel sources, patch configuration, recompile

# This overrides get_kernel_version from kernel.inc, so the variables will be set properly
get_kernel_version() {
	# Do not use MODULE_DIR here as this function might run when we process another module!
	[ -n "${TARGET_KERNEL_LONG}" ] && return 0
	[ ! -e "${ROOT_DIR}/tmp/work/kernel/ksrc/include/generated/utsrelease.h" ] && pinfo "No UTS information" && return 0
	# determine kernel version that will be running in the generated system

	# declare kernel version stuff
	declare -rg TARGET_KERNEL_LONG=$(grep 'UTS_RELEASE' "${ROOT_DIR}/tmp/work/kernel/ksrc/include/generated/utsrelease.h" | awk -F '"' '{print $2}')
	declare -rg TARGET_KERNEL_SHORT=$(echo "$TARGET_KERNEL_LONG" | grep -o -E '^[0-9\.]+')

	# declare path to kernel headers and modules/firmware
	declare -rg KERNEL_HEADERS_DIR="${ROOT_DIR}/tmp/work/kernel/ksrc"
	declare -rg KERNEL_BASE_DIR="${ROOT_DIR}/tmp/work/kernel/build"

	# print debug info
	pinfo  "TARGET_KERNEL_LONG:  '$TARGET_KERNEL_LONG'"
	pinfo  "TARGET_KERNEL_SHORT: '$TARGET_KERNEL_SHORT'"
	pdebug "KERNEL_BASE_DIR:     '$KERNEL_BASE_DIR'"
	pdebug "KERNEL_HEADERS_DIR:  '$KERNEL_HEADERS_DIR'"
}

fetch_source() {
	# Fetch all the firmware
	if ! [ -s "./fw/Makefile" ]; then
		rm -rf -- "./fw"
		git clone --depth 1 "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git" "./fw" \
			|| perror "Could not clone linux-firmware repo."
		rm -rf -- ./fw/LICENSE.* ./fw/*.txt
	fi
	if ! [ -s "./sof/install.sh" ]; then
		rm -rf -- "./sof"
		git clone --depth 1 "https://github.com/thesofproject/sof-bin.git" "./sof" \
			|| perror "Could not clone SOF"
	fi

	# Kernel - cached or freshly fetched
	if nfs_cache_avail; then
		local id tar
		id="$( kernel_build_id )"
		pinfo "Build id is $id"
		tar="${NFS_CACHE_DIR}/cache/${id}.tar.zstd"
		if [ -s "$tar" ]; then
			pinfo "Extracting cached kernel build"
			if < "$tar" zstd -d -T0 | tar -C "${MODULE_WORK_DIR}" -x; then
				touch "$tar" # We use last modified as last used, as atime is unreliable
				return 0
			fi
			pwarning "Extracting cached kernel failed, building..."
		fi
	fi
	fetch_kernel_source
}

fetch_kernel_source() {
	pdebug "getting kernel sources via git ...."
	if grep -q -- "${REQUIRED_GIT}" "./ksrc/.git/config" && grep -q -- "v${REQUIRED_KERNEL}" "./ksrc/.git/config"; then
		pinfo "Trying to update existing clone"
		cde ksrc
		git pull || perror "Could not pull already checked out repo"
		cde ..
	else
		rm -rf "./ksrc"
		git clone --depth 1 "${REQUIRED_GIT}" -b "v${REQUIRED_KERNEL}"  ksrc || perror "Could not clone kernel git."
	fi
	if [ -z "$MLTK_INSTALL" ]; then
		# check for aufs
		local RSL="$( find ksrc/ -type d -name aufs )"
		if [ -z "$RSL" ]; then
			pinfo "aufs not found in kernel sources, patching it..."
			patch_aufs
		else
			pinfo "aufs detected in kernel source :)"
		fi
	fi
	# Other patches
	local patch
	cde "$MODULE_WORK_DIR/ksrc"
	for patch in "${MODULE_DIR}/patches/"*${TARGET_KERNEL_SHORT%.*}*; do
		[ -f "$patch" ] || continue
		grep -q -F "$patch" "patches-done" && continue
		pinfo "Applying $(basename "$patch")"
		git apply < "$patch" || perror "Could not apply $patch"
		echo "$patch" >> "patches-done"
	done
}

build() {
	local bf="${MODULE_WORK_DIR}/ksrc/.mltk-build-flag"
	if ! [ -e "$bf"  ]; then
		local TARGET_CONFIG_FILE="${MODULE_WORK_DIR}/openslx.config"
		rm -f -- "${TARGET_CONFIG_FILE}"
		# update config and copy to ksrc
		pinfo "Updating kernel config..."
		update_config
		cp "${TARGET_CONFIG_FILE}" "ksrc/.config"
		# make kernel with the new config
		cde ksrc
		pinfo "Preparing kernel for new config ('make oldconfig')."
		if [ "x$MLTK_QUIET" = "x1" ]; then
			make olddefconfig || perror "make oldconfig failed."
		else
			make oldconfig || perror "make oldconfig failed."
		fi

		pinfo "Compiling kernel... (this will take some time)"
		# explicitly state number of cores here, as MAKEFLAGS seems to be overridden
		# also pass CC if set by core/includes/system.inc
		make $MAKEFLAGS ${CC:+CC=${CC}} || perror "make failed."
		touch "$bf"
		if nfs_cache_avail; then
			local id tar
			id="$( kernel_build_id )"
			tar="${NFS_CACHE_DIR}/cache/${id}.tar.zstd"
			pinfo "Copying built kernel to NFS cache with id $id"
			mkdir -p "$( dirname "$tar" )"
			tar -C "${MODULE_WORK_DIR}" -c -k ksrc | zstd -T0 -2 -z > "$tar" \
				|| pwarning "Could not write kernel to NFS cache"
		fi
	fi

	# install modules to build directory
	pinfo "Installing kernel modules..."
	cde "${MODULE_WORK_DIR}/ksrc"
	if [ -d "${MODULE_BUILD_DIR}/lib/modules" ]; then
		rm -r "${MODULE_BUILD_DIR}/lib/modules" || pwarning "Could not clean old modules."
	fi
	make INSTALL_MOD_PATH="${MODULE_BUILD_DIR}" INSTALL_MOD_STRIP=1 modules_install || perror "make modules_install failed in ${MODULE_BUILD_DIR}."

	# copy most recent firmware
	cde "${MODULE_WORK_DIR}"
	mkdir -p "${MODULE_BUILD_DIR}/lib/firmware/intel" "${MODULE_BUILD_DIR}/usr/bin"
	rm -rf -- "${MODULE_BUILD_DIR}/lib/firmware/intel/sof" "${MODULE_BUILD_DIR}/lib/firmware/intel/sof-tplg"
	cp -r ./fw/* "${MODULE_BUILD_DIR}/lib/firmware/" || perror "Could not copy linux-firmware to '${MODULE_BUILD_DIR}/lib/firmware/'"
	cde sof
	FW_DEST="${MODULE_BUILD_DIR}/lib/firmware/intel" \
		TOOLS_DEST="${MODULE_BUILD_DIR}/usr/bin" \
		./install.sh v2.1.x/v2.1.1 || perror "Installing sof firmware failed"
	cde ..

	# copy kernel to build
	cp ksrc/arch/x86/boot/bzImage "${MODULE_BUILD_DIR}/kernel" || perror "Could not copy bzImage"
	pinfo "Kernel was successfully built at ${MODULE_BUILD_DIR}/kernel"
	[ -z "${KERNEL_BUILD_DIR}" ] && KERNEL_BUILD_DIR="${MODULE_BUILD_DIR}"
}

post_copy() {
	:
}

# Get unique ID for this build configuration and environment
kernel_build_id() {
	local conf
	conf="$( kernel_config_base )"
	{
		[ -n "$conf" ] && grep -E '^(# )?CONFIG_' "$conf" # Base config
		cat "${ROOT_DIR}/data/kernel.wanted.config" # Wanted config
		gcc --version 2>&1 # gcc version might be important
		echo "${REQUIRED_KERNEL} ${MLTK_INSTALL}" # wanted kernel version, whether we run install mode
		cat "${MODULE_DIR}/patches/"* 2> /dev/null # any local patches
	} | md5sum | cut -c1-32
}

# Get path of kernel config zu base this kernel on; empty if none exists
kernel_config_base() {
	local src
	for src in "/boot/config-mltk" "/boot/config-$(uname -r)"; do
		if [ -s "$src" ]; then
			echo "$src"
			return 0
		fi
	done
	if [ -f "/proc/config.gz" ]; then
		zcat "/proc/config.gz" > "${ROOT_DIR}/tmp/kernel-config"
		echo "${ROOT_DIR}/tmp/kernel-config"
	fi
}

# helper function to update the current kernel config with our parameters
update_config() {
	local src_config_file wanted_config_file wanted_line option value current_line
	# first we need to update the current config
	src_config_file="$( kernel_config_base )"
	if [ -n "$src_config_file" ]; then
		pinfo "Using $src_config_file as a starting point"
	else
		pwarning "Using default config in the kernel repository as base config."
		make -C "${MODULE_WORK_DIR}/ksrc" defconfig
		[ -e "${MODULE_WORK_DIR}/ksrc/.config" ] || perror "Failed to create default kernel config."
		src_config_file="${MODULE_WORK_DIR}/ksrc/.config"
	fi

	# check for our wanted config parameter
	wanted_config_file="${ROOT_DIR}/data/kernel.wanted.config"

	[ -e "${wanted_config_file}" ] || perror "$wanted_config_file does not exist! Please add a list of wanted kernel config parameters."

	# copy basic config file
	cp "$src_config_file" "$TARGET_CONFIG_FILE"

	while read -r wanted_line || [ -n "$wanted_line" ]; do
		option="${wanted_line%%=*}"
		value="${wanted_line#*=}"
		current_line="$( grep -E -m1 "^(# )?${option}[= ]" "$src_config_file" )"

		[ "$current_line" = "$wanted_line" ] && continue
		[ "$value" = "n" ] && [ "$current_line" = "# ${option} is not set" ] && continue
		#echo "Process: $SEARCH_RESULT"
		# analyse results
		if [ -z "$current_line" ]; then
			# no match, add it
			echo "$wanted_line" >> "$TARGET_CONFIG_FILE"
		else
			# match, change to our setting if they differ
			sed -r -i "s/^(# )?${option}[= ].*\$/${wanted_line}/" "$TARGET_CONFIG_FILE"
		fi
	done < "$wanted_config_file"
}

# helper to patch aufs
patch_aufs() {
	local KERNEL_MAJOR=${REQUIRED_KERNEL%%.*}
	local AUFS="aufs${KERNEL_MAJOR}"
	pinfo "Cloning ${AUFS} standalone git"
	cde "${MODULE_WORK_DIR}"
	[ -d "${AUFS}-standalone/.git" ] && rm -rf "${AUFS}-standalone"		# if already there, kill it.
	# git: --depth 1 won't work here due to later "checkout origin/branch"
	if [ "$KERNEL_MAJOR" = "3" ]; then
		git clone "git://aufs.git.sourceforge.net/gitroot/aufs/${AUFS}-standalone.git" || perror "Cloning ${AUFS} failed."
	else
		git clone "https://github.com/sfjro/${AUFS}-standalone.git" || perror "Cloning ${AUFS} failed."
		#git clone "https://github.com/bnied/${AUFS}-standalone.git" || perror "Cloning ${AUFS} failed."
	fi
	# get the needed version
	cde "${MODULE_WORK_DIR}/${AUFS}-standalone"
	local branches=( $( git branch -r | grep -oE 'aufs[0-9\.\+]+$' ) )
	local major minor patch
	IFS=. read major minor patch _ <<<"$REQUIRED_KERNEL"
	if [ -z "$major" ] || [ -z "$minor" ]; then
		perror "REQUIRED_KERNEL not in properly set, this should not happen!"
	fi
	local testvar outer NEEDED_BRANCH
	while (( minor >= 0 )); do
		NEEDED_BRANCH="aufs${major}.${minor}"
		outer=false
		while (( patch > 0 )); do
			for testvar in "${branches[@]}"; do
				if [ "$testvar" = "${NEEDED_BRANCH}.${patch}" ] || [ "$testvar" = "${NEEDED_BRANCH}.${patch}+" ]; then
					NEEDED_BRANCH="$testvar"
					break 3
				elif [ "$testvar" = "${NEEDED_BRANCH}" ]; then
					outer=true
				fi
			done
			(( patch-- ))
		done
		$outer && break
		if (( patch == 0 )); then
			patch=500
			(( minor-- ))
		fi
	done
	pinfo "Getting branch origin/$NEEDED_BRANCH"
	git checkout "origin/$NEEDED_BRANCH" || git checkout "origin/${AUFS}.x-rcN" || perror "Could not checkout needed branch."
	pinfo "Starting to patch... $NEEDED_BRANCH"
	tarcopy "Documentation fs" "$MODULE_WORK_DIR/ksrc"

	# Quick-and-dirty aufs_type.h copying:
	[ -e "include/linux/aufs_type.h" ] && cp "include/linux/aufs_type.h" "$MODULE_WORK_DIR/ksrc/include/linux/"
	[ -e "include/uapi/linux/aufs_type.h" ] && cp "include/uapi/linux/aufs_type.h" "$MODULE_WORK_DIR/ksrc/include/uapi/linux/"

	cde "$MODULE_WORK_DIR/ksrc"

	local PATCH
	# Mandatory
	for PATCH in "${AUFS}-kbuild" "${AUFS}-base" "${AUFS}-mmap"; do
		patch -p1 < "$MODULE_WORK_DIR/${AUFS}-standalone/${PATCH}.patch" || perror "${PATCH}.patch failed!"
		pinfo "Applied '$MODULE_WORK_DIR/${AUFS}-standalone/${PATCH}.patch'"
	done
	# Optional - should we error too?
	for PATCH in "${AUFS}-loopback" "tmpfs-idr" "vfs-ino"; do
		[ -e "$MODULE_WORK_DIR/${AUFS}-standalone/${PATCH}.patch" ] || continue
		patch -p1 < "$MODULE_WORK_DIR/${AUFS}-standalone/${PATCH}.patch" || pwarning "${PATCH}.patch failed!"
		pinfo "Applied '$MODULE_WORK_DIR/${AUFS}-standalone/${PATCH}.patch'"
	done
	pinfo "Patched kernel source with ${NEEDED_BRANCH}"
	cde "$MODULE_WORK_DIR"
}