diff options
Diffstat (limited to 'payloads')
-rw-r--r-- | payloads/libpayload/util/xcompile/xcompile | 317 |
1 files changed, 210 insertions, 107 deletions
diff --git a/payloads/libpayload/util/xcompile/xcompile b/payloads/libpayload/util/xcompile/xcompile index 859688cc4d..1af02ad28a 100644 --- a/payloads/libpayload/util/xcompile/xcompile +++ b/payloads/libpayload/util/xcompile/xcompile @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # This file is part of the coreboot project. # @@ -20,6 +20,7 @@ # TMPFILE="" +XGCCPATH=${1:-"`pwd`/util/crossgcc/xgcc/bin/"} die() { echo "ERROR: $*" >&2 @@ -32,46 +33,78 @@ clean_up() { fi } +# Create temporary file(s). +TMPFILE="$(mktemp /tmp/temp.XXXX 2>/dev/null || echo /tmp/temp.78gOIUGz)" +touch "$TMPFILE" +trap clean_up EXIT + + program_exists() { type "$1" >/dev/null 2>&1 } + +if [ "$(${XGCCPATH}/iasl 2>/dev/null | grep -c ACPI)" -gt 0 ]; then + IASL=${XGCCPATH}iasl +elif [ "$(iasl 2>/dev/null | grep -c ACPI)" -gt 0 ]; then + IASL=iasl +else + die "no iasl found" +fi + +if program_exists gcc; then + HOSTCC=gcc +elif program_exists cc; then + HOSTCC=cc +else + die "no host compiler found" +fi + +cat <<EOF +# platform agnostic and host tools +IASL:=${IASL} +HOSTCC?=${HOSTCC} + +EOF + testcc() { local tmp_c="$TMPFILE.c" local tmp_o="$TMPFILE.o" rm -f "$tmp_c" "$tmp_o" - echo "_start(void) {}" >"$tmp_c" - "$1" -nostdinc -nostdlib -Werror $2 "$tmp_c" -o "$tmp_o" >/dev/null 2>&1 + echo "void _start(void) {}" >"$tmp_c" + "$1" -nostdlib -Werror $2 "$tmp_c" -o "$tmp_o" >/dev/null 2>&1 } testas() { - local gccprefixes="$1" + local gccprefix="$1" local twidth="$2" local arch="$3" local use_dash_twidth="$4" + local endian="$5" local obj_file="$TMPFILE.o" local full_arch="elf$twidth-$arch" rm -f "$obj_file" [ -n "$use_dash_twidth" ] && use_dash_twidth="--$twidth" - ${gccprefixes}as $use_dash_twidth -o "$obj_file" $TMPFILE 2>/dev/null || - return 1 + [ -n "$endian" ] && endian="-$endian" + ${gccprefix}as $use_dash_twidth $endian -o "$obj_file" $TMPFILE \ + 2>/dev/null || return 1 # Check output content type. - local obj_type="$(${gccprefixes}objdump -p $obj_file)" + local obj_type="$(${gccprefix}objdump -p $obj_file)" local obj_arch="$(expr "$obj_type" : '.*format \(.[a-z0-9-]*\)')" [ "$obj_arch" = "$full_arch" ] || return 1 # Architecture matched. - GCCPREFIX="$gccprefixes" + GCCPREFIX="$gccprefix" - if [ -z "$use_dash_twidth" ]; then - ASFLAGS="" - CFLAGS="" - LDFLAGS="" - else + unset ASFLAGS LDFLAGS + unset CFLAGS_GCC CFLAGS_CLANG + + if [ -n "$use_dash_twidth" ]; then ASFLAGS="--$twidth" - CFLAGS="-m$twidth" + CFLAGS_GCC="-m$twidth" + CFLAGS_CLANG="-m$twidth" LDFLAGS="-b $full_arch" fi @@ -80,7 +113,8 @@ testas() { [ -n "$use_dash_twidth" ] && case "$full_arch" in "elf32-i386" ) LDFLAGS="$LDFLAGS -melf_i386" - CFLAGS="$CFLAGS -Wl,-b,elf32-i386 -Wl,-melf_i386" + CFLAGS_GCC="$CFLAGS_GCC -Wl,-b,elf32-i386 -Wl,-melf_i386" + CFLAGS_CLANG="$CFLAGS_GCC -Wl,-b,elf32-i386 -Wl,-melf_i386" ;; esac @@ -91,94 +125,160 @@ detect_special_flags() { local architecture="$1" # GCC 4.6 is much more picky about unused variables. # Turn off it's warnings for now: - testcc "$CC" "$CFLAGS -Wno-unused-but-set-variable " && - CFLAGS="$CFLAGS -Wno-unused-but-set-variable " + testcc "$GCC" "$CFLAGS_GCC -Wno-unused-but-set-variable " && + CFLAGS_GCC="$CFLAGS_GCC -Wno-unused-but-set-variable " + + # Check for an operational -m32/-m64 + testcc "$GCC" "$CFLAGS_GCC -m$TWIDTH " && + CFLAGS_GCC="$CFLAGS_GCC -m$TWIDTH " # Use bfd linker instead of gold if available: - testcc "$CC" "$CFLAGS -fuse-ld=bfd" && - CFLAGS="$CFLAGS -fuse-ld=bfd" && LINKER_SUFFIX='.bfd' + testcc "$GCC" "$CFLAGS_GCC -fuse-ld=bfd" && + CFLAGS_GCC="$CFLAGS_GCC -fuse-ld=bfd" && LINKER_SUFFIX='.bfd' - testcc "$CC" "$CFLAGS -Wa,--divide" && - CFLAGS="$CFLAGS -Wa,--divide" - testcc "$CC" "$CFLAGS -fno-stack-protector"&& - CFLAGS="$CFLAGS -fno-stack-protector" - testcc "$CC" "$CFLAGS -Wl,--build-id=none" && - CFLAGS="$CFLAGS -Wl,--build-id=none" + testcc "$GCC" "$CFLAGS_GCC -fno-stack-protector"&& + CFLAGS_GCC="$CFLAGS_GCC -fno-stack-protector" + testcc "$GCC" "$CFLAGS_GCC -Wl,--build-id=none" && + CFLAGS_GCC="$CFLAGS_GCC -Wl,--build-id=none" case "$architecture" in - arm ) - # testcc "$CC" "$CFLAGS -mcpu=cortex-a9" && - # CFLAGS="$CFLAGS -mcpu=cortex-a9" - ;; - - arm64-generic ) - ;; - mips ) - testcc "$CC" "CFLAGS -mxgot" && - CFLAGS="$CFLAGS -mxgot" - ;; + x86) + testcc "$GCC" "$CFLAGS_GCC -Wa,--divide" && + CFLAGS_GCC="$CFLAGS_GCC -Wa,--divide" + testcc "$CLANG" "$CFLAGS_CLANG -Wa,--divide" && + CFLAGS_CLANG="$CFLAGS_CLANG -Wa,--divide" + # Always build for i686 -- no sse/mmx instructions since SMM + # modules are compiled using these flags. Note that this + # doesn't prevent a project using xcompile to explicitly + # specify -mmsse, etc flags. + CFLAGS_GCC="$CFLAGS_GCC -march=i686" + ;; + x64) + testcc "$GCC" "$CFLAGS_GCC -Wa,--divide" && + CFLAGS_GCC="$CFLAGS_GCC -Wa,--divide" + testcc "$CLANG" "$CFLAGS_CLANG -Wa,--divide" && + CFLAGS_CLANG="$CFLAGS_CLANG -Wa,--divide" + ;; + mipsel) + testcc "$GCC" "$CFLAGS_GCC -mno-abicalls -fno-pic" && \ + CFLAGS_GCC+=" -mno-abicalls -fno-pic" + + # Enforce little endian mode. + testcc "$GCC" "$CFLAGS_GCC -EL" && \ + CFLAGS_GCC+=" -EL" + ;; esac } +detect_compiler_runtime() { + test -z "$CLANG" || \ + CC_RT_CLANG="`${CLANG} ${CFLAGS} -print-librt-file-name 2>/dev/null`" + test -z "$GCC" || \ + CC_RT_GCC="`${GCC} ${CFLAGS} -print-libgcc-file-name`" +} + report_arch_toolchain() { cat <<EOF -# elf${TWIDTH}-${TBFDARCH} toolchain (${GCCPREFIX}gcc) -CC_${TARCH}:=${GCCPREFIX}gcc ${CFLAGS} +# elf${TWIDTH}-${TBFDARCH} toolchain (${GCC}) +ARCH_SUPPORTED+=${TARCH} +SUBARCH_SUPPORTED+=${TSUPP-${TARCH}} +ifeq (\$(CONFIG_COMPILER_GCC),y) +CC_${TARCH}:=${GCC} +CFLAGS_${TARCH}:=${CFLAGS_GCC} +COMPILER_RT_${TARCH}:=${CC_RT_GCC} +COMPILER_RT_FLAGS_${TARCH}:=${CC_RT_EXTRA_GCC} +else +CC_${TARCH}:=${CLANG} +CFLAGS_${TARCH}:=${CFLAGS_CLANG} +CFLAGS_${TARCH}+=-no-integrated-as -Qunused-arguments -m${TWIDTH} +# tone down compiler warnings +CFLAGS_${TARCH}+=-Wno-unused-variable -Wno-unused-function -Wno-tautological-compare -Wno-shift-overflow +COMPILER_RT_${TARCH}:=${CC_RT_CLANG} +COMPILER_RT_FLAGS_${TARCH}:=${CC_RT_EXTRA_CLANG} +endif +CPP_${TARCH}:=${GCCPREFIX}cpp AS_${TARCH}:=${GCCPREFIX}as ${ASFLAGS} -LD_${TARCH}:=${GCCPREFIX}ld ${LDFLAGS} +LD_${TARCH}:=${GCCPREFIX}ld${LINKER_SUFFIX} ${LDFLAGS} NM_${TARCH}:=${GCCPREFIX}nm OBJCOPY_${TARCH}:=${GCCPREFIX}objcopy OBJDUMP_${TARCH}:=${GCCPREFIX}objdump READELF_${TARCH}:=${GCCPREFIX}readelf STRIP_${TARCH}:=${GCCPREFIX}strip AR_${TARCH}:=${GCCPREFIX}ar +CROSS_COMPILE_${TARCH}:=${GCCPREFIX} EOF } -# Create temporary file(s). -TMPFILE="$(mktemp /tmp/temp.XXXX 2>/dev/null || echo /tmp/temp.78gOIUGz)" -touch "$TMPFILE" -trap clean_up EXIT +# Architecture definitions +SUPPORTED_ARCHITECTURES="arm arm64 mipsel riscv x64 x86" -# Architecture definition -SUPPORTED_ARCHITECTURE="arm arm64 mipsel x86" +arch_config_arm() { + TARCH="arm" + TBFDARCHS="littlearm" + TCLIST="armv7a armv7-a" + TWIDTH="32" + TSUPP="arm armv4 armv7 armv7_m" + TABI="eabi" +} -# ARM Architecture -TARCH_arm="arm" -TBFDARCH_arm="littlearm" -TCLIST_arm="armv7a armv7-a" -TWIDTH_arm="32" +arch_config_arm64() { + TARCH="arm64" + TBFDARCHS="littleaarch64" + TCLIST="aarch64" + TWIDTH="64" + TSUPP="arm64 armv8_64" + TABI="elf" +} -# ARM64 Architecture -TARCH_arm64="arm64" -TBFDARCH_arm64="littleaarch64" -TCLIST_arm64="aarch64" -TWIDTH_arm64="64" +arch_config_riscv() { + TARCH="riscv" + TBFDARCHS="littleriscv" + TCLIST="riscv" + TWIDTH="64" + TABI="elf" +} -# MIPS Architecture (Little Endian) -TARCH_mipsel="mipsel" -TBFDARCH_mipsel="tradlittlemips littlemips" -TCLIST_mipsel="mipsel" -TWIDTH_mipsel="32" +arch_config_x64() { + TARCH="x86_64" + TBFDARCHS="x86-64" + TCLIST="x86_64" + TWIDTH="64" + TABI="elf" +} -# X86 Architecture -TARCH_x86="i386" -TBFDARCH_x86="i386" -TCLIST_x86="i386 x86_64" -TWIDTH_x86="32" +arch_config_x86() { + TARCH="x86_32" + TBFDARCHS="i386" + TCLIST="i386 x86_64" + TWIDTH="32" + TABI="elf" + CC_RT_EXTRA_GCC="--wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3" +} -XGCCPATH=${1:-"`pwd`/../../util/crossgcc/xgcc/bin/"} +arch_config_mipsel() { + TARCH="mips" + TBFDARCHS="tradlittlemips littlemips" + TCLIST="mipsel" + TWIDTH="32" + TSUPP="mips mipsel" + TABI="elf" + TENDIAN="EL" +} + +test_architecture() { + local architecture=$1 + local endian gccprefix search -# This loops over all supported architectures. -for architecture in $SUPPORTED_ARCHITECTURE; do GCCPREFIX="invalid" - TARCH="$(eval echo \$TARCH_$architecture)" - TBFDARCHS="$(eval echo \$TBFDARCH_$architecture)" - TCLIST="$(eval echo \$TCLIST_$architecture)" - TWIDTH="$(eval echo \$TWIDTH_$architecture)" - [ -z "$TARCH" -o -z "$TCLIST" -o -z "$TWIDTH" ] && - die "Missing architecture definition for $architecture." + unset TABI TARCH TBFDARCH TCLIST TENDIAN TSUPP TWIDTH + unset CC_RT_EXTRA_GCC CC_RT_EXTRA_CLANG + unset GCC CLANG + if type arch_config_$architecture > /dev/null; then + arch_config_$architecture + else + die "no architecture definition for $architecture" + fi # To override toolchain, define CROSS_COMPILE_$arch or CROSS_COMPILE as # environment variable. @@ -187,48 +287,51 @@ for architecture in $SUPPORTED_ARCHITECTURE; do search="$(eval echo \$CROSS_COMPILE_$architecture 2>/dev/null)" search="$search $CROSS_COMPILE" for toolchain in $TCLIST; do - search="$search $XGCCPATH$toolchain-elf-" - search="$search $toolchain-elf-" - search="$search $XGCCPATH$toolchain-eabi-" - search="$search $toolchain-eabi-" + search="$search $XGCCPATH$toolchain-$TABI-" + search="$search $toolchain-$TABI-" + search="$search $toolchain-linux-gnu-" + search="$search $toolchain-" done echo "# $architecture TARCH_SEARCH=$search" # Search toolchain by checking assembler capability. for TBFDARCH in $TBFDARCHS; do - for gccprefixes in $search ""; do - program_exists "${gccprefixes}as" || continue - testas "$gccprefixes" "$TWIDTH" "$TBFDARCH" "" && break - testas "$gccprefixes" "$TWIDTH" "$TBFDARCH" "TRUE" && break + for gccprefix in $search ""; do + program_exists "${gccprefix}as" || continue + for endian in $TENDIAN ""; do + testas "$gccprefix" "$TWIDTH" "$TBFDARCH" \ + "" "$endian" && break 3 + testas "$gccprefix" "$TWIDTH" "$TBFDARCH" \ + "TRUE" "$endian" && break 3 + done done - [ "$GCCPREFIX" = "invalid" ] || break done - - if [ "$GCCPREFIX" = "invalid" ]; then - echo "Warning: no suitable GCC for $architecture." >&2 - continue + if [ "invalid" != "$GCCPREFIX" ]; then + GCC="${GCCPREFIX}gcc" fi - CC="${GCCPREFIX}"gcc - detect_special_flags "$architecture" - report_arch_toolchain -done - -if [ "$(${XGCCPATH}/iasl 2>/dev/null | grep -c ACPI)" -gt 0 ]; then - IASL=${XGCCPATH}iasl -else - IASL=iasl -fi + for clang_arch in $TCLIST invalid; do + testcc "clang" "-target ${clang_arch}-$TABI -c" && break + done -if program_exists gcc; then - HOSTCC=gcc -else - HOSTCC=cc -fi + if [ "invalid" != "$clang_arch" ]; then + # FIXME: this may break in a clang && !gcc configuration, + # but that's more of a clang limitation. Let's be optimistic + # that this will change in the future. + CLANG="clang -target ${clang_arch}-${TABI} -ccc-gcc-name ${GCC}" + fi -cat <<EOF -IASL:=${IASL} + if [ -z "$GCC" -a -z "$CLANG" ]; then + echo "Warning: no suitable compiler for $architecture." >&2 + return 1 + fi +} -# native toolchain -HOSTCC:=${HOSTCC} -EOF +# This loops over all supported architectures. +for architecture in $SUPPORTED_ARCHITECTURES; do + if test_architecture $architecture; then + detect_special_flags "$architecture" + detect_compiler_runtime "$architecture" + report_arch_toolchain + fi +done |