1#!/bin/sh 2# enable automatic i386/ARM/M68K/MIPS/SPARC/PPC/s390 program execution by the kernel 3 4qemu_target_list="i386 i486 alpha arm sparc32plus ppc ppc64 ppc64le m68k \ 5mips mipsel mipsn32 mipsn32el mips64 mips64el \ 6sh4 sh4eb s390x aarch64" 7 8i386_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00' 9i386_mask='\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff' 10i386_family=i386 11 12i486_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00' 13i486_mask='\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff' 14i486_family=i386 15 16alpha_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x26\x90' 17alpha_mask='\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff' 18alpha_family=alpha 19 20arm_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00' 21arm_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff' 22arm_family=arm 23 24armeb_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28' 25armeb_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff' 26armeb_family=arm 27 28sparc_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02' 29sparc_mask='\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff' 30sparc_family=sparc 31 32sparc32plus_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x12' 33sparc32plus_mask='\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff' 34sparc32plus_family=sparc 35 36ppc_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14' 37ppc_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff' 38ppc_family=ppc 39 40ppc64_magic='\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x15' 41ppc64_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff' 42ppc64_family=ppc 43 44ppc64le_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x15\x00' 45ppc64le_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\x00' 46ppc64le_family=ppcle 47 48m68k_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x04' 49m68k_mask='\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff' 50m68k_family=m68k 51 52# FIXME: We could use the other endianness on a MIPS host. 53 54mips_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08' 55mips_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff' 56mips_family=mips 57 58mipsel_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00' 59mipsel_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff' 60mipsel_family=mips 61 62mipsn32_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08' 63mipsn32_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff' 64mipsn32_family=mips 65 66mipsn32el_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00' 67mipsn32el_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff' 68mipsn32el_family=mips 69 70mips64_magic='\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08' 71mips64_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff' 72mips64_family=mips 73 74mips64el_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00' 75mips64el_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff' 76mips64el_family=mips 77 78sh4_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00' 79sh4_mask='\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff' 80sh4_family=sh4 81 82sh4eb_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a' 83sh4eb_mask='\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff' 84sh4eb_family=sh4 85 86s390x_magic='\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x16' 87s390x_mask='\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff' 88s390x_family=s390x 89 90aarch64_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00' 91aarch64_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff' 92aarch64_family=arm 93 94qemu_get_family() { 95 cpu=${HOST_ARCH:-$(uname -m)} 96 case "$cpu" in 97 amd64|i386|i486|i586|i686|i86pc|BePC|x86_64) 98 echo "i386" 99 ;; 100 mips*) 101 echo "mips" 102 ;; 103 "Power Macintosh"|ppc64|powerpc|ppc) 104 echo "ppc" 105 ;; 106 ppc64el|ppc64le) 107 echo "ppcle" 108 ;; 109 arm|armel|armhf|arm64|armv[4-9]*) 110 echo "arm" 111 ;; 112 sparc*) 113 echo "sparc" 114 ;; 115 *) 116 echo "$cpu" 117 ;; 118 esac 119} 120 121usage() { 122 cat <<EOF 123Usage: qemu-binfmt-conf.sh [--qemu-path PATH][--debian][--systemd CPU] 124 [--help][--credential yes|no][--exportdir PATH] 125 126 Configure binfmt_misc to use qemu interpreter 127 128 --help: display this usage 129 --qemu-path: set path to qemu interpreter ($QEMU_PATH) 130 --debian: don't write into /proc, 131 instead generate update-binfmts templates 132 --systemd: don't write into /proc, 133 instead generate file for systemd-binfmt.service 134 for the given CPU 135 --exportdir: define where to write configuration files 136 (default: $SYSTEMDDIR or $DEBIANDIR) 137 --credential: if yes, credential and security tokens are 138 calculated according to the binary to interpret 139 140 To import templates with update-binfmts, use : 141 142 sudo update-binfmts --importdir ${EXPORTDIR:-$DEBIANDIR} --import qemu-CPU 143 144 To remove interpreter, use : 145 146 sudo update-binfmts --package qemu-CPU --remove qemu-CPU $QEMU_PATH 147 148 With systemd, binfmt files are loaded by systemd-binfmt.service 149 150 The environment variable HOST_ARCH allows to override 'uname' to generate 151 configuration files for a different architecture than the current one. 152 153 where CPU is one of: 154 155 $qemu_target_list 156 157EOF 158} 159 160qemu_check_access() { 161 if [ ! -w "$1" ] ; then 162 echo "ERROR: cannot write to $1" 1>&2 163 exit 1 164 fi 165} 166 167qemu_check_bintfmt_misc() { 168 # load the binfmt_misc module 169 if [ ! -d /proc/sys/fs/binfmt_misc ]; then 170 if ! /sbin/modprobe binfmt_misc ; then 171 exit 1 172 fi 173 fi 174 if [ ! -f /proc/sys/fs/binfmt_misc/register ]; then 175 if ! mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc ; then 176 exit 1 177 fi 178 fi 179 180 qemu_check_access /proc/sys/fs/binfmt_misc/register 181} 182 183installed_dpkg() { 184 dpkg --status "$1" > /dev/null 2>&1 185} 186 187qemu_check_debian() { 188 if [ ! -e /etc/debian_version ] ; then 189 echo "WARNING: your system is not a Debian based distro" 1>&2 190 elif ! installed_dpkg binfmt-support ; then 191 echo "WARNING: package binfmt-support is needed" 1>&2 192 fi 193 qemu_check_access "$EXPORTDIR" 194} 195 196qemu_check_systemd() { 197 if ! systemctl -q is-enabled systemd-binfmt.service ; then 198 echo "WARNING: systemd-binfmt.service is missing or disabled" 1>&2 199 fi 200 qemu_check_access "$EXPORTDIR" 201} 202 203qemu_generate_register() { 204 echo ":qemu-$cpu:M::$magic:$mask:$qemu:$FLAGS" 205} 206 207qemu_register_interpreter() { 208 echo "Setting $qemu as binfmt interpreter for $cpu" 209 qemu_generate_register > /proc/sys/fs/binfmt_misc/register 210} 211 212qemu_generate_systemd() { 213 echo "Setting $qemu as binfmt interpreter for $cpu for systemd-binfmt.service" 214 qemu_generate_register > "$EXPORTDIR/qemu-$cpu.conf" 215} 216 217qemu_generate_debian() { 218 cat > "$EXPORTDIR/qemu-$cpu" <<EOF 219package qemu-$cpu 220interpreter $qemu 221magic $magic 222mask $mask 223EOF 224 if [ "$FLAGS" = "OC" ] ; then 225 echo "credentials yes" >> "$EXPORTDIR/qemu-$cpu" 226 fi 227} 228 229qemu_set_binfmts() { 230 # probe cpu type 231 host_family=$(qemu_get_family) 232 233 # register the interpreter for each cpu except for the native one 234 235 for cpu in ${qemu_target_list} ; do 236 magic=$(eval echo \$${cpu}_magic) 237 mask=$(eval echo \$${cpu}_mask) 238 family=$(eval echo \$${cpu}_family) 239 240 if [ "$magic" = "" ] || [ "$mask" = "" ] || [ "$family" = "" ] ; then 241 echo "INTERNAL ERROR: unknown cpu $cpu" 1>&2 242 continue 243 fi 244 245 qemu="$QEMU_PATH/qemu-$cpu" 246 if [ "$cpu" = "i486" ] ; then 247 qemu="$QEMU_PATH/qemu-i386" 248 fi 249 250 if [ "$host_family" != "$family" ] ; then 251 $BINFMT_SET 252 fi 253 done 254} 255 256CHECK=qemu_check_bintfmt_misc 257BINFMT_SET=qemu_register_interpreter 258 259SYSTEMDDIR="/etc/binfmt.d" 260DEBIANDIR="/usr/share/binfmts" 261 262QEMU_PATH=/usr/local/bin 263FLAGS="" 264 265options=$(getopt -o ds:Q:e:hc: -l debian,systemd:,qemu-path:,exportdir:,help,credential: -- "$@") 266eval set -- "$options" 267 268while true ; do 269 case "$1" in 270 -d|--debian) 271 CHECK=qemu_check_debian 272 BINFMT_SET=qemu_generate_debian 273 EXPORTDIR=${EXPORTDIR:-$DEBIANDIR} 274 ;; 275 -s|--systemd) 276 CHECK=qemu_check_systemd 277 BINFMT_SET=qemu_generate_systemd 278 EXPORTDIR=${EXPORTDIR:-$SYSTEMDDIR} 279 shift 280 # check given cpu is in the supported CPU list 281 for cpu in ${qemu_target_list} ; do 282 if [ "$cpu" == "$1" ] ; then 283 break 284 fi 285 done 286 287 if [ "$cpu" == "$1" ] ; then 288 qemu_target_list="$1" 289 else 290 echo "ERROR: unknown CPU \"$1\"" 1>&2 291 usage 292 exit 1 293 fi 294 ;; 295 -Q|--qemu-path) 296 shift 297 QEMU_PATH="$1" 298 ;; 299 -e|--exportdir) 300 shift 301 EXPORTDIR="$1" 302 ;; 303 -h|--help) 304 usage 305 exit 1 306 ;; 307 -c|--credential) 308 shift 309 if [ "$1" = "yes" ] ; then 310 FLAGS="OC" 311 else 312 FLAGS="" 313 fi 314 ;; 315 *) 316 break 317 ;; 318 esac 319 shift 320done 321 322$CHECK 323qemu_set_binfmts 324