edk2-funcs.sh (6922B)
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 23 qemu_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 45 qemu_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 75 qemu_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 99 qemu_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 elif ( [ -e /etc/debian_version ] && [ "$gcc_arch" == arm ] ); then 116 # force soft-float cross-compiler on Debian 117 printf 'arm-linux-gnueabi-' 118 else 119 printf '%s-linux-gnu-\n' "$gcc_arch" 120 fi 121 } 122 123 124 # Determine the edk2 toolchain tag for the QEMU system emulation target. Print 125 # the result to the standard output. Print a message to the standard error, and 126 # return with nonzero status, if the (conditional) gcc version check fails. 127 # 128 # Parameters: 129 # $1: QEMU system emulation target 130 qemu_edk2_get_toolchain() 131 { 132 local emulation_target="$1" 133 local program_name=$(basename -- "$0") 134 local cross_prefix 135 local gcc_version 136 137 if ! qemu_edk2_verify_arch "$emulation_target"; then 138 return 1 139 fi 140 141 case "$emulation_target" in 142 (arm|aarch64) 143 printf 'GCC5\n' 144 ;; 145 146 (i386|x86_64) 147 if ! cross_prefix=$(qemu_edk2_get_cross_prefix "$emulation_target"); then 148 return 1 149 fi 150 151 gcc_version=$("${cross_prefix}gcc" -v 2>&1 | tail -1 | awk '{print $3}') 152 # Run "git-blame" on "OvmfPkg/build.sh" in edk2 for more information on 153 # the mapping below. 154 case "$gcc_version" in 155 ([1-3].*|4.[0-7].*) 156 printf '%s: unsupported gcc version "%s"\n' \ 157 "$program_name" "$gcc_version" >&2 158 return 1 159 ;; 160 (4.8.*) 161 printf 'GCC48\n' 162 ;; 163 (4.9.*|6.[0-2].*) 164 printf 'GCC49\n' 165 ;; 166 (*) 167 printf 'GCC5\n' 168 ;; 169 esac 170 ;; 171 esac 172 } 173 174 175 # Determine the name of the environment variable that exposes the 176 # cross-compiler prefix to the edk2 "build" utility. Print the result to the 177 # standard output. 178 # 179 # Parameters: 180 # $1: QEMU system emulation target 181 qemu_edk2_get_cross_prefix_var() 182 { 183 local emulation_target="$1" 184 local edk2_toolchain 185 local edk2_arch 186 187 if ! edk2_toolchain=$(qemu_edk2_get_toolchain "$emulation_target"); then 188 return 1 189 fi 190 191 case "$emulation_target" in 192 (arm|aarch64) 193 if ! edk2_arch=$(qemu_edk2_get_arch "$emulation_target"); then 194 return 1 195 fi 196 printf '%s_%s_PREFIX\n' "$edk2_toolchain" "$edk2_arch" 197 ;; 198 (i386|x86_64) 199 printf '%s_BIN\n' "$edk2_toolchain" 200 ;; 201 esac 202 } 203 204 205 # Set and export the environment variable(s) necessary for cross-compilation, 206 # whenever needed by the edk2 "build" utility. 207 # 208 # Parameters: 209 # $1: QEMU system emulation target 210 qemu_edk2_set_cross_env() 211 { 212 local emulation_target="$1" 213 local cross_prefix 214 local cross_prefix_var 215 216 if ! cross_prefix=$(qemu_edk2_get_cross_prefix "$emulation_target"); then 217 return 1 218 fi 219 220 if [ -z "$cross_prefix" ]; then 221 # Nothing to do. 222 return 0 223 fi 224 225 if ! cross_prefix_var=$(qemu_edk2_get_cross_prefix_var \ 226 "$emulation_target"); then 227 return 1 228 fi 229 230 eval "export $cross_prefix_var=\$cross_prefix" 231 } 232 233 234 # Determine the "-n" option argument (that is, the number of modules to build 235 # in parallel) for the edk2 "build" utility. Print the result to the standard 236 # output. 237 # 238 # Parameters: 239 # $1: the value of the MAKEFLAGS variable 240 qemu_edk2_get_thread_count() 241 { 242 local makeflags="$1" 243 244 if [[ "$makeflags" == *--jobserver-auth=* ]] || 245 [[ "$makeflags" == *--jobserver-fds=* ]]; then 246 # If there is a job server, allow the edk2 "build" utility to parallelize 247 # as many module builds as there are logical CPUs in the system. The "make" 248 # instances forked by "build" are supposed to limit themselves through the 249 # job server. The zero value below causes the edk2 "build" utility to fetch 250 # the logical CPU count with Python's multiprocessing.cpu_count() method. 251 printf '0\n' 252 else 253 # Build a single module at a time. 254 printf '1\n' 255 fi 256 } 257 258 259 # Work around <https://bugzilla.tianocore.org/show_bug.cgi?id=1607> by 260 # filtering jobserver-related flags out of MAKEFLAGS. Print the result to the 261 # standard output. 262 # 263 # Parameters: 264 # $1: the value of the MAKEFLAGS variable 265 qemu_edk2_quirk_tianocore_1607() 266 { 267 local makeflags="$1" 268 269 printf %s "$makeflags" \ 270 | LC_ALL=C sed --regexp-extended \ 271 --expression='s/--jobserver-(auth|fds)=[0-9]+,[0-9]+//' \ 272 --expression='s/-j([0-9]+)?//' 273 }