1#!/bin/bash
2
3#
4# Board Configuration Section
5# ===========================
6#
7# Board configuration moved to parse-platforms.py and platforms.config.
8#
9# No need to edit below unless you are changing script functionality.
10#
11
12unset WORKSPACE EDK_TOOLS_DIR MAKEFLAGS
13
14TOOLS_DIR="`dirname $0`"
15export TOOLS_DIR
16. "$TOOLS_DIR"/common-functions
17PLATFORM_CONFIG=""
18VERBOSE=0
19ATF_DIR=
20TOS_DIR=
21TOOLCHAIN=
22OPENSSL_CONFIGURED=FALSE
23
24# Number of threads to use for build
25export NUM_THREADS=$((`getconf _NPROCESSORS_ONLN` + 1))
26
27function do_build
28{
29	PLATFORM_NAME="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o longname`"
30	PLATFORM_PREBUILD_CMDS="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o prebuild_cmds`"
31	PLATFORM_BUILDFLAGS="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o buildflags`"
32	PLATFORM_BUILDFLAGS="$PLATFORM_BUILDFLAGS ${EXTRA_OPTIONS[@]}"
33	PLATFORM_BUILDCMD="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o buildcmd`"
34	PLATFORM_DSC="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o dsc`"
35	PLATFORM_PACKAGES_PATH="$PWD"
36	COMPONENT_INF="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o inf`"
37
38	PLATFORM_ARCH="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o arch`"
39	if [ -n "$PLATFORM_ARCH" ]; then
40		if [ -n "$DEFAULT_PLATFORM_ARCH" -a "$DEFAULT_PLATFORM_ARCH" != "$PLATFORM_ARCH" ]; then
41			echo "Command line specified architecture '$DEFAULT_PLATFORM_ARCH'" >&2
42			echo "differs from config file specified '$PLATFORM_ARCH'" >&2
43			return 1
44		fi
45	else
46		if [ ! -n "$DEFAULT_PLATFORM_ARCH" ]; then
47			echo "Unknown target architecture - aborting!" >&2
48			return 1
49		fi
50		PLATFORM_ARCH="$DEFAULT_PLATFORM_ARCH"
51	fi
52	TEMP_PACKAGES_PATH="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o packages_path`"
53	if [ -n "$TEMP_PACKAGES_PATH" ]; then
54		IFS=:
55		for path in "$TEMP_PACKAGES_PATH"; do
56			case "$path" in
57				/*)
58					PLATFORM_PACKAGES_PATH="$PLATFORM_PACKAGES_PATH:$path"
59				;;
60				*)
61					PLATFORM_PACKAGES_PATH="$PLATFORM_PACKAGES_PATH:$PWD/$path"
62				;;
63		        esac
64		done
65		unset IFS
66	fi
67	if [ $VERBOSE -eq 1 ]; then
68		echo "Setting build parallellism to $NUM_THREADS processes\n"
69		echo "PLATFORM_NAME=$PLATFORM_NAME"
70		echo "PLATFORM_PREBUILD_CMDS=$PLATFORM_PREBUILD_CMDS"
71		echo "PLATFORM_BUILDFLAGS=$PLATFORM_BUILDFLAGS"
72		echo "PLATFORM_BUILDCMD=$PLATFORM_BUILDCMD"
73		echo "PLATFORM_DSC=$PLATFORM_DSC"
74		echo "PLATFORM_ARCH=$PLATFORM_ARCH"
75		echo "PLATFORM_PACKAGES_PATH=$PLATFORM_PACKAGES_PATH"
76	fi
77
78	if [[ "${PLATFORM_BUILDFLAGS}" =~ "SECURE_BOOT_ENABLE=TRUE" ]]; then
79	    import_openssl
80	fi
81
82	if [ -n "$CROSS_COMPILE_64" -a "$PLATFORM_ARCH" == "AARCH64" ]; then
83		TEMP_CROSS_COMPILE="$CROSS_COMPILE_64"
84	elif [ -n "$CROSS_COMPILE_32" -a "$PLATFORM_ARCH" == "ARM" ]; then
85		TEMP_CROSS_COMPILE="$CROSS_COMPILE_32"
86	else
87		set_cross_compile
88	fi
89
90	CROSS_COMPILE="$TEMP_CROSS_COMPILE"
91
92	echo "Building $PLATFORM_NAME - $PLATFORM_ARCH"
93	echo "CROSS_COMPILE=\"$TEMP_CROSS_COMPILE\""
94	echo "$board"_BUILDFLAGS="'$PLATFORM_BUILDFLAGS'"
95
96	if [ "$TARGETS" == "" ]; then
97		TARGETS=( RELEASE )
98	fi
99
100	case $TOOLCHAIN in
101		"gcc")
102			TOOLCHAIN=`get_gcc_version "$CROSS_COMPILE"gcc`
103			if [ $? -ne 0 ]; then
104				echo "${CROSS_COMPILE}gcc not found!" >&2
105				return 1
106			fi
107			;;
108		"clang")
109			TOOLCHAIN=`get_clang_version clang`
110			if [ $? -ne 0 ]; then
111				return 1
112			fi
113			;;
114	esac
115	export TOOLCHAIN
116	echo "TOOLCHAIN is ${TOOLCHAIN}"
117
118	export ${TOOLCHAIN}_${PLATFORM_ARCH}_PREFIX=$CROSS_COMPILE
119	echo "Toolchain prefix: ${TOOLCHAIN}_${PLATFORM_ARCH}_PREFIX=$CROSS_COMPILE"
120
121	export PACKAGES_PATH="$PLATFORM_PACKAGES_PATH"
122	for target in "${TARGETS[@]}" ; do
123		if [ X"$PLATFORM_PREBUILD_CMDS" != X"" ]; then
124			echo "Run pre build commands"
125			eval ${PLATFORM_PREBUILD_CMDS}
126		fi
127
128		if [ -n "$COMPONENT_INF" ]; then
129			# Build a standalone component
130			build -n $NUM_THREADS -a "$PLATFORM_ARCH" -t ${TOOLCHAIN} -p "$PLATFORM_DSC" \
131				-m "$COMPONENT_INF" -b "$target" ${PLATFORM_BUILDFLAGS}
132		else
133			# Build a platform
134			build -n $NUM_THREADS -a "$PLATFORM_ARCH" -t ${TOOLCHAIN} -p "$PLATFORM_DSC" \
135				-b "$target" ${PLATFORM_BUILDFLAGS}
136		fi
137
138		RESULT=$?
139		if [ $RESULT -eq 0 ]; then
140			if [ X"$TOS_DIR" != X"" ]; then
141				pushd $TOS_DIR >/dev/null
142				if [ $VERBOSE -eq 1 ]; then
143					echo "$TOOLS_DIR/tos-build.sh -e "$EDK2_DIR" -t "$target"_${TOOLCHAIN} $board"
144				fi
145				$TOOLS_DIR/tos-build.sh -e "$EDK2_DIR" -t "$target"_${TOOLCHAIN} $board
146				RESULT=$?
147				popd >/dev/null
148			fi
149		fi
150		if [ $RESULT -eq 0 ]; then
151			if [ X"$ATF_DIR" != X"" ]; then
152				pushd $ATF_DIR >/dev/null
153				if [ $VERBOSE -eq 1 ]; then
154					echo "$TOOLS_DIR/atf-build.sh -e "$EDK2_DIR" -t "$target"_${TOOLCHAIN} $board"
155				fi
156				$TOOLS_DIR/atf-build.sh -e "$EDK2_DIR" -t "$target"_${TOOLCHAIN} $board
157				RESULT=$?
158				popd >/dev/null
159			fi
160		fi
161		result_log $RESULT "$PLATFORM_NAME $target"
162	done
163	unset PACKAGES_PATH
164}
165
166
167function clearcache
168{
169  CONF_FILES="build_rule target tools_def"
170  if [ -z "$EDK_TOOLS_PATH" ]
171  then
172    TEMPLATE_PATH=./BaseTools/Conf/
173  else
174    TEMPLATE_PATH="$EDK_TOOLS_PATH/Conf/"
175  fi
176
177  for File in $CONF_FILES
178  do
179    TEMPLATE_FILE="$TEMPLATE_PATH/$File.template"
180    CACHE_FILE="Conf/$File.txt"
181    if [ -e "$CACHE_FILE" -a "$TEMPLATE_FILE" -nt "$CACHE_FILE" ]
182    then
183      echo "Removing outdated '$CACHE_FILE'."
184      rm "$CACHE_FILE"
185    fi
186  done
187
188  unset TEMPLATE_PATH TEMPLATE_FILE CACHE_FILE
189}
190
191
192function uefishell
193{
194	BUILD_ARCH=`uname -m`
195	case $BUILD_ARCH in
196		arm*)
197			ARCH=ARM
198			;;
199		aarch64)
200			ARCH=AARCH64
201			;;
202		*)
203			unset ARCH
204			;;
205	esac
206	export ARCH
207	export EDK_TOOLS_PATH=`pwd`/BaseTools
208	clearcache
209	. edksetup.sh BaseTools
210	if [ $VERBOSE -eq 1 ]; then
211		echo "Building BaseTools"
212	fi
213	make -C $EDK_TOOLS_PATH
214	if [ $? -ne 0 ]; then
215		echo " !!! UEFI BaseTools failed to build !!! " >&2
216		exit 1
217	fi
218}
219
220
221function usage
222{
223	echo "usage:"
224	echo -n "uefi-build.sh [-b DEBUG | RELEASE] [ all "
225	for board in "${boards[@]}" ; do
226	    echo -n "| $board "
227	done
228	echo "]"
229	printf "%8s\tbuild %s\n" "all" "all supported platforms"
230	for board in "${boards[@]}" ; do
231		PLATFORM_NAME="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG -p $board get -o longname`"
232		printf "%8s\tbuild %s\n" "$board" "${PLATFORM_NAME}"
233	done
234}
235
236#
237# Since we do a command line validation on whether specified platforms exist or
238# not, do a first pass of command line to see if there is an explicit config
239# file there to read valid platforms from.
240#
241commandline=( "$@" )
242i=0
243for arg;
244do
245	if [ $arg == "-c" ]; then
246		FILE_ARG=${commandline[i + 1]}
247		if [ ! -f "$FILE_ARG" ]; then
248			echo "ERROR: configuration file '$FILE_ARG' not found" >&2
249			exit 1
250		fi
251		case "$FILE_ARG" in
252			/*)
253				PLATFORM_CONFIG="-c $FILE_ARG"
254			;;
255			*)
256				PLATFORM_CONFIG="-c `readlink -f \"$FILE_ARG\"`"
257			;;
258		esac
259		echo "Platform config file: '$FILE_ARG'"
260		export PLATFORM_CONFIG
261	fi
262	i=$(($i + 1))
263done
264
265builds=()
266boards=()
267boardlist="`$TOOLS_DIR/parse-platforms.py $PLATFORM_CONFIG shortlist`"
268for board in $boardlist; do
269    boards=(${boards[@]} $board)
270done
271
272NUM_TARGETS=0
273
274while [ "$1" != "" ]; do
275	case $1 in
276		all )
277			builds=(${boards[@]})
278			NUM_TARGETS=$(($NUM_TARGETS + 1))
279			;;
280		"/h" | "/?" | "-?" | "-h" | "--help" )
281			usage
282			exit
283			;;
284		"-v" )
285			VERBOSE=1
286			;;
287		"-a" )
288			shift
289			ATF_DIR="$1"
290			;;
291		"-A" )
292			shift
293			DEFAULT_PLATFORM_ARCH="$1"
294			;;
295		"-c" )
296			# Already parsed above - skip this + option
297			shift
298			;;
299		"-s" )
300			shift
301			export TOS_DIR="$1"
302			;;
303		"-b" | "--build" )
304			shift
305			echo "Adding Build profile: $1"
306			TARGETS=( ${TARGETS[@]} $1 )
307			;;
308		"-D" )
309			shift
310			echo "Adding option: -D $1"
311			EXTRA_OPTIONS=( ${EXTRA_OPTIONS[@]} "-D" $1 )
312			;;
313		"-T" )
314			shift
315			echo "Setting toolchain to '$1'"
316			TOOLCHAIN="$1"
317			;;
318		"-1" )
319			NUM_THREADS=1
320			;;
321		* )
322			MATCH=0
323			for board in "${boards[@]}" ; do
324				if [ "$1" == $board ]; then
325					MATCH=1
326					builds=(${builds[@]} "$board")
327					break
328				fi
329			done
330
331			if [ $MATCH -eq 0 ]; then
332				echo "unknown arg $1"
333				usage
334				exit 1
335			fi
336			NUM_TARGETS=$(($NUM_TARGETS + 1))
337			;;
338	esac
339	shift
340done
341
342# If there were no args, use a menu to select a single board / all boards to build
343if [ $NUM_TARGETS -eq 0 ]
344then
345	read -p "$(
346			f=0
347			for board in "${boards[@]}" ; do
348					echo "$((++f)): $board"
349			done
350			echo $((++f)): all
351
352			echo -ne '> '
353	)" selection
354
355	if [ "$selection" -eq $((${#boards[@]} + 1)) ]; then
356		builds=(${boards[@]})
357	else
358		builds="${boards[$((selection-1))]}"
359	fi
360fi
361
362# Check to see if we are in a UEFI repository
363# refuse to continue if we aren't
364if [ ! -e BaseTools ]
365then
366	echo "ERROR: we aren't in the UEFI directory."
367	echo "       I can tell because I can't see the BaseTools directory"
368	exit 1
369fi
370
371EDK2_DIR="$PWD"
372export VERBOSE
373
374if [[ "${EXTRA_OPTIONS[@]}" != *"FIRMWARE_VER"* ]]; then
375	if test -d .git && head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
376		FIRMWARE_VER=`git rev-parse --short HEAD`
377		if ! git diff-index --quiet HEAD --; then
378			FIRMWARE_VER="${FIRMWARE_VER}-dirty"
379		fi
380		EXTRA_OPTIONS=( ${EXTRA_OPTIONS[@]} "-D" FIRMWARE_VER=$FIRMWARE_VER )
381		if [ $VERBOSE -eq 1 ]; then
382			echo "FIRMWARE_VER=$FIRMWARE_VER"
383			echo "EXTRA_OPTIONS=$EXTRA_OPTIONS"
384		fi
385	fi
386fi
387
388uefishell
389
390if [ X"$TOOLCHAIN" = X"" ]; then
391	TOOLCHAIN=gcc
392fi
393
394for board in "${builds[@]}" ; do
395	do_build
396done
397
398result_print
399