summaryrefslogtreecommitdiff
path: root/ti_config_fragments/defconfig_builder.sh
blob: e9961c3d1cc8bfe6661d6875bb74a1de81a1e259 (plain)
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
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
#!/bin/bash
#
#  defconfig_builder.sh
#
#  Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
#  ALL RIGHTS RESERVED
#
#  This script will perform a merge of config fragment files into a defconfig
#  based on a map file.  The map file defines the defconfig options that have
#  been tested by TI to boot and compile.
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  For more information type defconfig_builder.sh -?
#
# IMPORTANT NOTE: All modifications to this script must be verified by running
# 'shellcheck --shell=bash defconfig_builder.sh' See 'Installing' section in:
# https://github.com/koalaman/shellcheck/blob/master/README.md
# Also note that shellcheck must be at least at revision 0.3.3

DEBUG_CONFIG_TAG="debug_options"
CONFIG_FRAGMENT_TAG="config-fragment="
DISCLAIMER="\n*Please be advised that the Debug Option defconfigs may\nimpact \
performance and should only be used for debugging.\n"

# Template for temporary build files.. use PID to differentiate
TMP_PREFIX=ti_defconfig_builder_$$
TMP_TEMPLATE="$TMP_PREFIX"_XXXXX.tmp

set_working_directory() {
	SCRIPT_PATH=$(readlink -f $(dirname "${BASH_SOURCE[0]}"))

	if [ ! -v KERNEL_PATH ]; then
		if [ -f $(pwd)/MAINTAINERS ]; then
			KERNEL_PATH=$(pwd)
		else
			KERNEL_PATH=$SCRIPT_PATH/../../linux/
		fi
	fi

	KERNEL_PATH=$(readlink -f $KERNEL_PATH)

	if [ ! -f $KERNEL_PATH/MAINTAINERS ]; then
		echo "Error: $KERNEL_PATH does not look like a kernel directory"
		exit 1
	fi
}

prepare_for_exit() {
	D=$(dirname "$PROCESSOR_FILE")
	rm -f "$PROCESSOR_FILE"
	rm -f "$BUILD_TYPE_FILE"
	rm -f "$TEMP_TYPE_FILE"
	if [ -s "$OLD_CONFIG" ]; then
		mv "$OLD_CONFIG" "$KERNEL_PATH"/.config
	fi
	# Clean everyone else up if we missed any
	rm -f "$D"/"$TMP_PREFIX"*.tmp
	exit
}

check_for_config_existance() {
	# Check to make sure that the config fragments exist
	TEMP_EXTRA_CONFIG_FILE=$(echo "$BUILD_DETAILS" | cut -d: -f6)
	if [ -z "$TEMP_EXTRA_CONFIG_FILE" ]; then
		CONFIG_FRAGMENTS=
	else
		for CONFIG_FRAGMENT_FILE in $TEMP_EXTRA_CONFIG_FILE;
		do
			# If we do already point to existing file, we are good.
			if [ -e "$CONFIG_FRAGMENT_FILE" ]; then
				CONFIG_FRAG="$CONFIG_FRAGMENT_FILE"
			else
				# Assume it is present in TI working path
				CONFIG_FRAG="$SCRIPT_PATH/$CONFIG_FRAGMENT_FILE"
			fi
			if [ ! -e "$CONFIG_FRAG" ]; then
				CONFIG_FRAGMENTS="N/A"
			fi
		done
	fi

	if ! grep -qc "$BT_TEMP" "$BUILD_TYPE_FILE"; then
		# If the config file and config fragments are available
		# add it to the list.
		CONFIG_FILE=$(echo "$BUILD_DETAILS" | awk '{print$8}')
		if [ "$CONFIG_FILE" = "None" ]; then
			CONFIG_FILE=
		else
			if [ -e "$SCRIPT_PATH""/""$CONFIG_FILE" ]; then
				CONFIG_FILE=
			fi
		fi
		# If the check for the config file and the config fragments
		# pass then these two variables should be empty.  If
		# they fail then they should be N/A.
		if [ -z "$CONFIG_FILE" -a -z "$CONFIG_FRAGMENTS" ]; then
			max_configs=$((max_configs+1))
			echo -e '\t'"$max_configs". "$BT_TEMP" >> "$BUILD_TYPE_FILE"
		fi
	fi
}

choose_build_type() {
	TEMP_BT_FILE=$(mktemp -t $TMP_TEMPLATE)
	TEMP_BUILD_FILE=$(mktemp -t $TMP_TEMPLATE)

	grep "$DEFCONFIG_FILTER" "$DEFCONFIG_MAP_FILE" | grep "^classification:" | awk '{print$4}' > "$TEMP_BUILD_FILE"

	max_configs=0
	while true;
	do
		CONFIG_FILE=
		CONFIG_FRAGMENTS=

		BT_TEMP=$(head -n 1 "$TEMP_BUILD_FILE")
		if [ -z "$BT_TEMP" ]; then
			break
		fi
		BUILD_DETAILS=$(grep -w "$BT_TEMP" "$DEFCONFIG_MAP_FILE")
		check_for_config_existance
		sed -i "1d" "$TEMP_BUILD_FILE"
	done

	NUM_OF_BUILDS=$(wc -l "$BUILD_TYPE_FILE" | awk '{print$1}')
	if [ "$NUM_OF_BUILDS" -eq 0 ]; then
		echo "Sorry no build targets for this configuration.  Are you on the right branch?"
		prepare_for_exit
	fi

	# Force the user to answer.  Maybe the user does not want to continue
	while true;
	do
		echo -e "Available ""$DEFCONFIG_FILTER"" defconfig build options:\n"
		cat "$BUILD_TYPE_FILE"
		echo ""
		read -p "Please enter the number of the defconfig to build or 'q' to exit: " REPLY

		if [ "$REPLY" = "q" -o "$REPLY" = "Q" ]; then
			prepare_for_exit
		elif ! [[ "$REPLY" =~ ^[0-9]+$ ]]; then
			echo -e "\n$REPLY is not a number of the defconfig.  Please try again!\n"
			continue
		elif [ "$REPLY" -gt '0' -a "$REPLY" -le "$NUM_OF_BUILDS" ]; then
			CHOSEN_BUILD_TYPE=$(grep -w "$REPLY" "$BUILD_TYPE_FILE" | awk '{print$2}')
			break
		else
			echo -e "\n'$REPLY' is not a valid choice. Please \
choose a value between '1' and '$max_configs':\n"
		fi
	done
	rm "$TEMP_BT_FILE"
	rm "$TEMP_BUILD_FILE"
}

list_all_targets() {

	TMP_MAP=$(mktemp -t $TMP_TEMPLATE)

	count=0
	max_types=0
	while [ "x${SUPPORTED_ARCH[max_types]}" != "x" ]
	do
		DEFCONFIG_MAP_FILE=${SUPPORTED_ARCH[(count * 3) + 2]}
		count=$(( $count + 1 ))
		max_types=$(( $max_types + 3 ))
		if [ ! -e "$DEFCONFIG_MAP_FILE" ]; then
			continue
		fi

		cat "$DEFCONFIG_MAP_FILE" > "$TMP_MAP"
		while true;
		do
			CONFIG_FILE=
			CONFIG_FRAGMENTS=

			BT_TEMP=$(head -n 1 "$TMP_MAP" | awk '{print$4}')
			BUILD_DETAILS=$(head -n 1 "$TMP_MAP")
			if [ -z "$BUILD_DETAILS" ]; then
				break
			fi
			check_for_config_existance
			sed -i "1d" "$TMP_MAP"
		done
		rm "$TMP_MAP"
	done
	cat "$BUILD_TYPE_FILE"
}

get_build_details() {
	count=0
	max_types=0
	while [ "x${SUPPORTED_ARCH[max_types]}" != "x" ]
	do
		DEFCONFIG_MAP_FILE=${SUPPORTED_ARCH[(count * 3) + 2]}
		if [ -e "$DEFCONFIG_MAP_FILE" ]; then
			BUILD_DETAILS=$(grep -w "$CHOSEN_BUILD_TYPE" "$DEFCONFIG_MAP_FILE")
			if [ ! -z "$BUILD_DETAILS" ]; then
				if [ -z ${DEFCONFIG_KERNEL_PATH} ]; then
					DEFCONFIG_KERNEL_PATH=${SUPPORTED_ARCH[(count * 3) + 1]}
				fi
				break
			fi
		fi

		count=$(( $count + 1 ))
		max_types=$(( $max_types + 3 ))
	done

	if [ -z "$BUILD_DETAILS" ]; then
		echo "Cannot find the build type or a match for $CHOSEN_BUILD_TYPE"
		TEMP_BUILD_FILE=$(mktemp -t $TMP_TEMPLATE)
		grep "$CHOSEN_BUILD_TYPE" "$DEFCONFIG_MAP_FILE" > "$TEMP_BUILD_FILE"
		while true;
		do
			CONFIG_FILE=
			CONFIG_FRAGMENTS=

			BT_TEMP=$(head -n 1 "$TEMP_BUILD_FILE" | awk '{print$4}')
			if [ -z "$BT_TEMP" ]; then
				break
			fi
			BUILD_DETAILS=$(grep -w "$BT_TEMP" "$DEFCONFIG_MAP_FILE")
			check_for_config_existance
			sed -i "1d" "$TEMP_BUILD_FILE"
		done
		rm -rf "$TEMP_BUILD_FILE"

		NUM_OF_BUILDS=$(wc -l "$BUILD_TYPE_FILE" | awk '{print$1}')
		if [ "$NUM_OF_BUILDS" -eq 0 ]; then
			echo "Maybe try one of the following:"
			list_all_targets
		else
			echo "Did you mean any of the following?"
			cat "$BUILD_TYPE_FILE"
		fi

		return 1
	fi

	DEFCONFIG=$(echo "$BUILD_DETAILS" | awk '{print$6}')
	DEFCONFIG="$DEFCONFIG_KERNEL_PATH""/""$DEFCONFIG"
	CONFIG_FILE=$(echo "$BUILD_DETAILS" | awk '{print$8}')
	# There may be a need to just build with the config fragments themselves
	if [ "$CONFIG_FILE" = "None" ]; then
		CONFIG_FILE=
	fi

	if [ ! -e "$SCRIPT_PATH/$CONFIG_FILE" ]; then
		echo "$SCRIPT_PATH/$CONFIG_FILE does not exist"
		return 1
	fi

	TEMP_EXTRA_CONFIG_FILE=$(echo "$BUILD_DETAILS" | cut -d: -f6)
	for CONFIG_FRAGMENT_FILE in $TEMP_EXTRA_CONFIG_FILE;
	do
		# If we do already point to existing file, we are good.
		if [ -e "$CONFIG_FRAGMENT_FILE" ]; then
			CONFIG_FRAG="$CONFIG_FRAGMENT_FILE"
		else
			# Assume it is present in TI working path
			CONFIG_FRAG="$SCRIPT_PATH/$CONFIG_FRAGMENT_FILE"
		fi
		if [ -e "$CONFIG_FRAG" ]; then
			EXTRA_CONFIG_FILE="$EXTRA_CONFIG_FILE $CONFIG_FRAG"
		else
			echo "$CONFIG_FRAG" does not exist
		fi
	done
}

build_defconfig() {

	if [ ! -z "$CONFIG_FILE" -a -e "$SCRIPT_PATH/$CONFIG_FILE" ]; then
		CONFIGS=$(grep "$CONFIG_FRAGMENT_TAG" "$SCRIPT_PATH/$CONFIG_FILE" | cut -d= -f2)
	fi

	"$KERNEL_PATH"/scripts/kconfig/merge_config.sh -m -r "$DEFCONFIG" \
		"$CONFIGS" "$EXTRA_CONFIG_FILE" > /dev/null

	if [ "$?" = "0" ];then
		if [ -z ${DEFCONFIG_OUT} ]; then
			echo "Creating defconfig file ""$DEFCONFIG_KERNEL_PATH/""$CHOSEN_BUILD_TYPE"_defconfig
			mv .config "$DEFCONFIG_KERNEL_PATH"/"$CHOSEN_BUILD_TYPE"_defconfig
		else
			if [ ! -d ${DEFCONFIG_OUT} ]; then
				mkdir -p ${DEFCONFIG_OUT}
			fi
			echo "Creating defconfig file ""$DEFCONFIG_OUT/""$CHOSEN_BUILD_TYPE"_defconfig
			mv .config ${DEFCONFIG_OUT}/${CHOSEN_BUILD_TYPE}_defconfig
		fi
	else
		echo "Defconfig creation failed"
		return 1
	fi
}

choose_defconfig_type() {

	TEMP_TYPE_FILE=$(mktemp -t $TMP_TEMPLATE)

	TYPE_FILE=$(awk '{print$2}' "$DEFCONFIG_MAP_FILE" | sort -u | grep -i ${TYPE})

	max_types=0
	for TYPE_TMP in $TYPE_FILE;
	do
		max_types=$((max_types+1))
		echo -e '\t' "$max_types." "$TYPE_TMP" >> "$TEMP_TYPE_FILE"
	done
	echo >> "$TEMP_TYPE_FILE"

	while true;
	do
		cat "$TEMP_TYPE_FILE"
		read -p "Please choose a defconfig type to build for or 'q' to exit: " REPLY
		if [ "$REPLY" = "q" -o "$REPLY" = "Q" ]; then
			prepare_for_exit
		elif ! [[ "$REPLY" =~ ^[0-9]+$ ]]; then
			echo -e "\n'$REPLY' is not a number for the build type.  Please try again!\n"
			continue
		elif [ "$REPLY" -gt '0' -a "$REPLY" -le "$max_types" ]; then
			REPLY="$REPLY""."
			DEFCONFIG_FILTER=$(awk '{if ($1 == "'"$REPLY"'") print $2;}' "$TEMP_TYPE_FILE")
			break
		else
			echo -e "\n'$REPLY' is not a valid choice. Please \
choose a value between '1' and '$max_types':\n"
		fi
	done

	DEBUG_BUILD=$(grep "$DEFCONFIG_FILTER" "$DEFCONFIG_MAP_FILE" | grep -wc "$DEBUG_CONFIG_TAG" )
	if [ "$DEBUG_BUILD" -gt '0' ]; then
		echo -e "$DISCLAIMER"
	fi
}

choose_architecture() {

	TEMP_ARCH_FILE=$(mktemp -t $TMP_TEMPLATE)

	max_types=0
	count=0
	while [ "x${SUPPORTED_ARCH[max_types]}" != "x" ]
	do
		ARCH_TYPE=${SUPPORTED_ARCH[max_types]}
		if [ -e "${SUPPORTED_ARCH[max_types + 2]}" ]; then
			count=$(( $count + 1 ))
			echo -e '\t' "$count." "$ARCH_TYPE" >> "$TEMP_ARCH_FILE"
		fi
		max_types=$(( $max_types + 3 ))
	done

	if [ "$count" -eq 1 ]; then
		REPLY=$count
	else
		while true;
		do
			cat "$TEMP_ARCH_FILE"
			read -p "Please choose an architecture to build for or 'q' to exit: " REPLY
			if [ "$REPLY" = "q" -o "$REPLY" = "Q" ]; then
				prepare_for_exit
			elif ! [[ "$REPLY" =~ ^[0-9]+$ ]]; then
				echo -e "\n'$REPLY' is not a number for the build type.  Please try again!\n"
				continue
			elif [ "$REPLY" -gt '0' -a "$REPLY" -le "$max_types" ]; then
				REPLY_DISP="$REPLY""."
				ARCH_TO_BUILD=$(awk '{if ($1 == "'"$REPLY_DISP"'") print $2;}' "$TEMP_ARCH_FILE")
				# System test configs are specific and contain
				# the v7 and v8 tags so we have to do something
				# special.
				if [ ${ARCH_TO_BUILD} == "System" ]; then
					SYSTEM_TEST_ARCH=$(awk '{if ($1 == "'"$REPLY_DISP"'") print $4;}' "$TEMP_ARCH_FILE")
					ARCH_TEST="System Test "${SYSTEM_TEST_ARCH}
				else
					ARCH_TEST=${ARCH_TO_BUILD}
				fi
				break
			else
				echo -e "\n'$REPLY' is not a valid choice. Please \
	choose a value between '1' and '$max_types':\n"
			fi
		done
	fi

	max_types=0
	while [ "x${SUPPORTED_ARCH[max_types]}" != "x" ]
	do
		ARCH_TYPE=${SUPPORTED_ARCH[max_types]}
		ARCH_COUNTER=$(grep -c "$ARCH_TEST" <<< $ARCH_TYPE)
		if [ "$ARCH_COUNTER" -gt 0 ]; then
			break
		fi
		max_types=$(( $max_types + 3 ))
	done

	DEFCONFIG_KERNEL_PATH=${SUPPORTED_ARCH[max_types + 1]}
	DEFCONFIG_MAP_FILE=${SUPPORTED_ARCH[max_types + 2]}
}

usage() {
cat << EOF

This script will perform a merge of config fragment files into a defconfig
based on a map file.  The map file defines the defconfig options that have
been tested by TI to boot and compile.

Optional:
	-k - Location of the Linux kernel source
	-w - Same as -k (deprecated)
	-t - Indicates the type of defconfig to build.  This will force the
	     defconfig to build without user interaction.
	-l - List all buildable defconfig options
	-o - Outputs the built defconfigs to a different directory.

Command line example to generate the TI SDK AM335x processor defconfig automatically
without user interaction:

	ti_config_fragments/defconfig_builder.sh -t ti_sdk_am3x_release

Command line Example if building from the ti_config_fragments directory:
	defconfig_builder.sh -w ../.

User interactive command line example:
	ti_config_fragments/defconfig_builder.sh
EOF
}

#########################################
# Script Start
#########################################
while getopts "?k:w:t:o:l" OPTION
do
	case $OPTION in
		k|w)
			KERNEL_PATH=$OPTARG;;
		t)
			CHOSEN_BUILD_TYPE=$OPTARG;;
		l)
			LIST_TARGETS="y";;
		o)
			DEFCONFIG_OUT=$OPTARG;;
		?)
			usage
			exit;;
     esac
done

trap prepare_for_exit SIGHUP EXIT SIGINT SIGTERM

set_working_directory

SUPPORTED_ARCH=(
"v7 ARM Architecture" "$KERNEL_PATH/arch/arm/configs" "$SCRIPT_PATH/defconfig_map.txt"
"v8 ARM Architecture" "$KERNEL_PATH/arch/arm64/configs" "$SCRIPT_PATH/v8_defconfig_map.txt"
"System Test v7 Builds" "$KERNEL_PATH/arch/arm/configs" "$SCRIPT_PATH/system_test/system_test_map.txt"
"System Test v8 Builds" "$KERNEL_PATH/arch/arm64/configs" "$SCRIPT_PATH/system_test/v8_system_test_map.txt")

BUILD_TYPE_FILE=$(mktemp -t $TMP_TEMPLATE)

if [ ! -z "$LIST_TARGETS" ]; then
	echo "The following are a list of buildable defconfigs:"
	list_all_targets
	exit 0
fi


PROCESSOR_FILE=$(mktemp -t $TMP_TEMPLATE)
OLD_CONFIG=$(mktemp -t $TMP_TEMPLATE)
if [ -f "$KERNEL_PATH"/.config ]; then
	mv "$KERNEL_PATH"/.config "$OLD_CONFIG"
fi

if [ ! -z "$CHOSEN_BUILD_TYPE" ]; then
	get_build_details
	if [ "$?" -gt 0 ]; then
		exit 1
	fi

	build_defconfig
	if [ "$?" -gt 0 ]; then
		exit 1
	fi
	exit 0
fi

choose_architecture

if [ ! -e "$DEFCONFIG_MAP_FILE" ]; then
	echo "No defconfig map file found"
	exit 1
fi

if [ ${ARCH_TO_BUILD} == "System" ]; then
	TYPE="System_"
else
	TYPE="SDK_"
	choose_defconfig_type
fi

choose_build_type
get_build_details

build_defconfig