1# Shell script that defines functions for determining some environmental 2# characteristics for the edk2 "build" utility. 3# 4# This script is meant to be sourced, in a bash environment. 5# 6# Copyright (C) 2019 Red Hat, Inc. 7# 8# This program and the accompanying materials are licensed and made available 9# under the terms and conditions of the BSD License that accompanies this 10# distribution. The full text of the license may be found at 11# <http://opensource.org/licenses/bsd-license.php>. 12# 13# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT 14# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 15 16 17# Verify whether the QEMU system emulation target is supported by the UEFI spec 18# and edk2. Print a message to the standard error, and return with nonzero 19# status, if verification fails. 20# 21# Parameters: 22# $1: QEMU system emulation target 23qemu_edk2_verify_arch() 24{ 25 local emulation_target="$1" 26 local program_name=$(basename -- "$0") 27 28 case "$emulation_target" in 29 (arm|aarch64|i386|x86_64) 30 ;; 31 (*) 32 printf '%s: unknown/unsupported QEMU system emulation target "%s"\n' \ 33 "$program_name" "$emulation_target" >&2 34 return 1 35 ;; 36 esac 37} 38 39 40# Translate the QEMU system emulation target to the edk2 architecture 41# identifier. Print the result to the standard output. 42# 43# Parameters: 44# $1: QEMU system emulation target 45qemu_edk2_get_arch() 46{ 47 local emulation_target="$1" 48 49 if ! qemu_edk2_verify_arch "$emulation_target"; then 50 return 1 51 fi 52 53 case "$emulation_target" in 54 (arm) 55 printf 'ARM\n' 56 ;; 57 (aarch64) 58 printf 'AARCH64\n' 59 ;; 60 (i386) 61 printf 'IA32\n' 62 ;; 63 (x86_64) 64 printf 'X64\n' 65 ;; 66 esac 67} 68 69 70# Translate the QEMU system emulation target to the gcc cross-compilation 71# architecture identifier. Print the result to the standard output. 72# 73# Parameters: 74# $1: QEMU system emulation target 75qemu_edk2_get_gcc_arch() 76{ 77 local emulation_target="$1" 78 79 if ! qemu_edk2_verify_arch "$emulation_target"; then 80 return 1 81 fi 82 83 case "$emulation_target" in 84 (arm|aarch64|x86_64) 85 printf '%s\n' "$emulation_target" 86 ;; 87 (i386) 88 printf 'i686\n' 89 ;; 90 esac 91} 92 93 94# Determine the gcc cross-compiler prefix (if any) for use with the edk2 95# toolchain. Print the result to the standard output. 96# 97# Parameters: 98# $1: QEMU system emulation target 99qemu_edk2_get_cross_prefix() 100{ 101 local emulation_target="$1" 102 local gcc_arch 103 local host_arch 104 105 if ! gcc_arch=$(qemu_edk2_get_gcc_arch "$emulation_target"); then 106 return 1 107 fi 108 109 host_arch=$(uname -m) 110 111 if [ "$gcc_arch" == "$host_arch" ] || 112 ( [ "$gcc_arch" == i686 ] && [ "$host_arch" == x86_64 ] ); then 113 # no cross-compiler needed 114 : 115 else 116 printf '%s-linux-gnu-\n' "$gcc_arch" 117 fi 118} 119 120 121# Determine the edk2 toolchain tag for the QEMU system emulation target. Print 122# the result to the standard output. Print a message to the standard error, and 123# return with nonzero status, if the (conditional) gcc version check fails. 124# 125# Parameters: 126# $1: QEMU system emulation target 127qemu_edk2_get_toolchain() 128{ 129 local emulation_target="$1" 130 local program_name=$(basename -- "$0") 131 local cross_prefix 132 local gcc_version 133 134 if ! qemu_edk2_verify_arch "$emulation_target"; then 135 return 1 136 fi 137 138 case "$emulation_target" in 139 (arm|aarch64) 140 printf 'GCC5\n' 141 ;; 142 143 (i386|x86_64) 144 if ! cross_prefix=$(qemu_edk2_get_cross_prefix "$emulation_target"); then 145 return 1 146 fi 147 148 gcc_version=$("${cross_prefix}gcc" -v 2>&1 | tail -1 | awk '{print $3}') 149 # Run "git-blame" on "OvmfPkg/build.sh" in edk2 for more information on 150 # the mapping below. 151 case "$gcc_version" in 152 ([1-3].*|4.[0-7].*) 153 printf '%s: unsupported gcc version "%s"\n' \ 154 "$program_name" "$gcc_version" >&2 155 return 1 156 ;; 157 (4.8.*) 158 printf 'GCC48\n' 159 ;; 160 (4.9.*|6.[0-2].*) 161 printf 'GCC49\n' 162 ;; 163 (*) 164 printf 'GCC5\n' 165 ;; 166 esac 167 ;; 168 esac 169} 170 171 172# Determine the name of the environment variable that exposes the 173# cross-compiler prefix to the edk2 "build" utility. Print the result to the 174# standard output. 175# 176# Parameters: 177# $1: QEMU system emulation target 178qemu_edk2_get_cross_prefix_var() 179{ 180 local emulation_target="$1" 181 local edk2_toolchain 182 local edk2_arch 183 184 if ! edk2_toolchain=$(qemu_edk2_get_toolchain "$emulation_target"); then 185 return 1 186 fi 187 188 case "$emulation_target" in 189 (arm|aarch64) 190 if ! edk2_arch=$(qemu_edk2_get_arch "$emulation_target"); then 191 return 1 192 fi 193 printf '%s_%s_PREFIX\n' "$edk2_toolchain" "$edk2_arch" 194 ;; 195 (i386|x86_64) 196 printf '%s_BIN\n' "$edk2_toolchain" 197 ;; 198 esac 199} 200 201 202# Set and export the environment variable(s) necessary for cross-compilation, 203# whenever needed by the edk2 "build" utility. 204# 205# Parameters: 206# $1: QEMU system emulation target 207qemu_edk2_set_cross_env() 208{ 209 local emulation_target="$1" 210 local cross_prefix 211 local cross_prefix_var 212 213 if ! cross_prefix=$(qemu_edk2_get_cross_prefix "$emulation_target"); then 214 return 1 215 fi 216 217 if [ -z "$cross_prefix" ]; then 218 # Nothing to do. 219 return 0 220 fi 221 222 if ! cross_prefix_var=$(qemu_edk2_get_cross_prefix_var \ 223 "$emulation_target"); then 224 return 1 225 fi 226 227 eval "export $cross_prefix_var=\$cross_prefix" 228} 229 230 231# Determine the "-n" option argument (that is, the number of modules to build 232# in parallel) for the edk2 "build" utility. Print the result to the standard 233# output. 234# 235# Parameters: 236# $1: the value of the MAKEFLAGS variable 237qemu_edk2_get_thread_count() 238{ 239 local makeflags="$1" 240 241 if [[ "$makeflags" == *--jobserver-auth=* ]] || 242 [[ "$makeflags" == *--jobserver-fds=* ]]; then 243 # If there is a job server, allow the edk2 "build" utility to parallelize 244 # as many module builds as there are logical CPUs in the system. The "make" 245 # instances forked by "build" are supposed to limit themselves through the 246 # job server. The zero value below causes the edk2 "build" utility to fetch 247 # the logical CPU count with Python's multiprocessing.cpu_count() method. 248 printf '0\n' 249 else 250 # Build a single module at a time. 251 printf '1\n' 252 fi 253} 254