1#!/bin/bash -xe
2###############################################################################
3# Launch QEMU using the raw commands
4#
5#  Can be run by specifying the BASE_DIR and QEMU_ARCH when the script is
6#  called. Additionally, this script is automatically called by running the
7#  run-robot-qemu-test.sh, it's used to launch the QEMU test container.
8#
9###############################################################################
10#
11#  Variables BASE_DIR and QEMU_ARCH are both required but can be optionally
12#  input as parameters following the initial script call. Alternatively, they
13#  can be input by exporting them or sourcing the script into an environment
14#  that has them declared.
15#
16#  Parameters:
17#   parm1:  <optional, QEMU architecture to use >
18#            default is ${QEMU_ARCH} - ppc64le-linux or x86_64-linux
19#   parm2:  <optional, full path to base directory of qemu binary and images >
20#            default is ${HOME}
21#
22# Optional Env Variable:
23#
24#  QEMU_BIN           = Location of qemu-system-arm binary to use when starting
25#                       QEMU relative to upstream workspace.  Default is
26#                       ./tmp/sysroots/${QEMU_ARCH}/usr/bin/qemu-system-arm
27#                       which is the default location when doing a bitbake
28#                       of obmc-phosphor-image
29#
30#  MACHINE            = Machine to run test against. Options are "witherspoon",
31#                       "palmetto", "romulus", or undefined (default).  Default
32#                       will use the versatilepb model.
33###############################################################################
34
35set -uo pipefail
36
37QEMU_ARCH=${1:-$QEMU_ARCH}
38# If QEMU_ARCH is empty exit, it is required to continue
39echo "QEMU_ARCH = $QEMU_ARCH"
40if [[ -z $QEMU_ARCH ]]; then
41    echo "Did not pass in required QEMU arch parameter"
42    exit 1
43fi
44
45BASE_DIR=${2:-$HOME}
46# If BASE_DIR doesn't exist exit, it is required to continue
47echo "BASE_DIR = $BASE_DIR"
48if [[ ! -d $BASE_DIR ]]; then
49    echo "No input directory and HOME not set!"
50    exit 1
51fi
52
53# Set the location of the qemu binary relative to BASE_DIR
54QEMU_BIN=${QEMU_BIN:-./tmp/sysroots/${QEMU_ARCH}/usr/bin/qemu-system-arm}
55
56DEFAULT_MACHINE=versatilepb
57MACHINE=${MACHINE:-${DEFAULT_MACHINE}}
58
59# Enter the base directory
60cd "${BASE_DIR}"
61
62# Find the correct drive file, and save its name.  OpenBMC has 3 different
63# image formats.  The UBI based one, the standard static.mtd one, and the
64# default QEMU basic image (rootfs.ext4).
65DEFAULT_IMAGE_LOC="${DEFAULT_IMAGE_LOC:-./tmp/deploy/images/}"
66if [ -f "${DEFAULT_IMAGE_LOC}/${MACHINE}/obmc-phosphor-image-${MACHINE}".ubi.mtd ]; then
67    DRIVE="obmc-phosphor-image-${MACHINE}.ubi.mtd"
68elif [ -f "${DEFAULT_IMAGE_LOC}/${MACHINE}/obmc-phosphor-image-${MACHINE}".static.mtd ]; then
69    DRIVE="obmc-phosphor-image-${MACHINE}.static.mtd"
70else
71    # shellcheck disable=SC2010
72    DRIVE=$(ls "${DEFAULT_IMAGE_LOC}"/qemuarm | grep rootfs.ext4)
73fi
74
75# Copy the drive file off to /tmp so that QEMU does not write anything back
76# to the drive file and make it unusable for future QEMU runs.
77
78TMP_DRIVE_PATH=$(mktemp "/tmp/${DRIVE}-XXXXX")
79
80# The drive file is stored in different locations depending on if we are
81# using the default or real platforms.
82if [ "${MACHINE}" = "${DEFAULT_MACHINE}" ]; then
83    cp "${DEFAULT_IMAGE_LOC}/qemuarm/${DRIVE}" "${TMP_DRIVE_PATH}"
84else
85    cp "${DEFAULT_IMAGE_LOC}/${MACHINE}/${DRIVE}" "${TMP_DRIVE_PATH}"
86fi
87
88# Obtain IP from /etc/hosts if IP is not valid set to localhost
89IP=$(awk 'END{print $1}' /etc/hosts)
90if [[ "$IP" != *.*.*.* ]]; then
91    IP=127.0.0.1
92fi
93
94# Forward all needed ports for the robot test framework to run
95# Since this is run in docker, the standard ports can be used
96NET_FORWARDING=hostfwd=:${IP}:22-:22,hostfwd=:${IP}:443-:443,hostfwd=tcp:${IP}:80-:80,hostfwd=tcp:${IP}:2200-:2200,hostfwd=udp:${IP}:623-:623,hostfwd=udp:${IP}:664-:664
97
98# Most system only have one NIC so set this as default
99NIC="-net nic,model=ftgmac100,netdev=netdev1 -netdev user,id=netdev1,$NET_FORWARDING"
100if [ "${MACHINE}" = "tacoma" ]; then
101    # Tacoma requires us to specify up to four NICs, with the third one being
102    # the active device.
103    NIC="-net nic,model=ftgmac100,netdev=netdev1 -netdev user,id=netdev1 "
104    NIC+="-net nic,model=ftgmac100,netdev=netdev2 -netdev user,id=netdev2 "
105    NIC+="-net nic,model=ftgmac100,netdev=netdev3 -netdev user,id=netdev3,$NET_FORWARDING "
106    NIC+="-net nic,model=ftgmac100,netdev=netdev4 -netdev user,id=netdev4"
107fi
108
109# The syntax to start old qemu / default version requires different syntax
110# then new qemu with the real platforms
111if [ "${MACHINE}" = "${DEFAULT_MACHINE}" ]; then
112    # Launch default QEMU using the qemu-system-arm
113    ${QEMU_BIN} \
114        -device virtio-net,netdev=mynet \
115        -netdev "user,id=mynet,hostfwd=tcp:${IP}:22-:22,hostfwd=tcp:${IP}:443-:443,hostfwd=tcp:${IP}:80-:80,hostfwd=tcp:${IP}:2200-:2200,hostfwd=udp:${IP}:623-:623,hostfwd=udp:${IP}:664-:664" \
116        -machine versatilepb \
117        -m 256 \
118        -drive file="${TMP_DRIVE_PATH}",if=virtio,format=raw \
119        -show-cursor \
120        -usb \
121        -usbdevice tablet \
122        -device virtio-rng-pci \
123        -serial mon:vc \
124        -serial mon:stdio \
125        -serial null \
126        -kernel "${DEFAULT_IMAGE_LOC}"/qemuarm/zImage \
127        -append 'root=/dev/vda rw highres=off  console=ttyS0 mem=256M ip=dhcp console=ttyAMA0,115200 console=tty'\
128        -dtb "${DEFAULT_IMAGE_LOC}"/qemuarm/zImage-versatile-pb.dtb
129else
130    # shellcheck disable=SC2086 # NIC is intentionally word-split.
131    ${QEMU_BIN} \
132        -machine "${MACHINE}"-bmc \
133        -nographic \
134        -drive file="${TMP_DRIVE_PATH}",format=raw,if=mtd \
135        ${NIC}
136fi
137