1#!/bin/bash
2# SPDX-License-Identifier: BSD-3-Clause
3# Copyright(c) 2018 Intel Corporation. All rights reserved.
4set -e
5
6SUPPORTED_PLATFORMS=(byt cht bdw hsw apl icl skl kbl cnl imx8 imx8x imx8m)
7
8SOF_DIR=$(cd "$(dirname "$0")" && cd .. && pwd)
9
10: "${SOF_BUILDS:=${SOF_DIR}}"
11
12rm -f dump-*.txt
13
14die()
15{
16	>&2 printf '%s ERROR: ' "$0"
17	# We want die() to be usable exactly like printf
18	# shellcheck disable=SC2059
19	>&2 printf "$@"
20	exit 1
21}
22
23print_usage()
24{
25	cat <<EOF
26usage: qemu-check.sh [ platform(s) ]
27	Supported platforms are ${SUPPORTED_PLATFORMS[*]}
28	Runs all supported platforms by default.
29EOF
30}
31
32find_qemu_xtensa()
33{
34	local xhs=xtensa-host.sh
35	for d in . ../qemu* qemu*; do
36		if test -e "$d"/$xhs; then
37			printf '%s' "$d"/$xhs;
38			return
39		fi
40	done
41	die '%s not found\n' $xhs
42}
43
44
45while getopts "" OPTION; do
46	case "$OPTION" in
47		*) print_usage; exit 1 ;;
48	esac
49done
50shift $((OPTIND-1))
51
52PLATFORMS=()
53if [ "$#" -eq 0 ]; then
54	PLATFORMS=("${SUPPORTED_PLATFORMS[@]}")
55else
56	for arg in "$@"; do
57		platform=unknown
58		for sp in "${SUPPORTED_PLATFORMS[@]}"; do
59			if [ x"$sp" = x"$arg" ]; then
60				PLATFORMS=("${PLATFORMS[@]}" "$sp")
61				platform=$sp
62				shift
63				break
64			fi
65		done
66		if [ "$platform" = "unknown" ]; then
67			echo "Error: Unknown platform specified: $arg"
68			echo "Supported platforms: ${SUPPORTED_PLATFORMS[*]}"
69			exit 1
70		fi
71	done
72fi
73
74for platform in "${PLATFORMS[@]}"
75do
76	FWNAME="sof-$platform.ri"
77	PLATFORM=$platform
78	# reset variable to avoid issue in random order
79	ROM=''
80	OUTBOX_OFFSET=''
81
82	has_rom=false
83	case "$platform" in
84		byt)
85			READY_IPC="00 88 02 70 00 00 00 80"
86			SHM_IPC_REG=qemu-bridge-shim-io
87			SHM_MBOX=qemu-bridge-mbox-io
88			;;
89		cht)
90			READY_IPC="00 88 02 70 00 00 00 80"
91			SHM_IPC_REG=qemu-bridge-shim-io
92			SHM_MBOX=qemu-bridge-mbox-io
93			;;
94		bdw)
95			READY_IPC="00 3c 01 80"
96			OUTBOX_OFFSET="9e000"
97			SHM_IPC_REG=qemu-bridge-shim-io
98			SHM_MBOX=qemu-bridge-dram-mem
99			;;
100		hsw)
101		# This READY_IPC value comes from:
102		#   shim_write(SHIM_IPCD, outbox | SHIM_IPCD_BUSY);
103		#   outbox=MAILBOX_HOST_OFFSET >> 3;
104		#   MAILBOX_HOST_OFFSET>>3 = 0xFC00
105		#   IPC_DIPCIDR_BUSY = BIT(31)
106			READY_IPC="00 fc 00 80"
107			OUTBOX_OFFSET="7e000"
108			SHM_IPC_REG=qemu-bridge-shim-io
109			SHM_MBOX=qemu-bridge-dram-mem # some DMA traces visible here
110			;;
111		apl)
112		# This READY_IPC value comes from:
113		#   ipc_write(IPC_DIPCIDR, IPC_DIPCIDR_BUSY | header);
114		#   header = FE_READY = 0x7
115		#   IPC_DIPCIDR_BUSY = BIT(31)
116		# So "00 00 00 f0" is just "F0000000"
117			READY_IPC="00 00 00 f0"
118			SHM_IPC_REG="qemu-bridge-ipc(|-dsp)-io"
119			OUTBOX_OFFSET="7000"
120			SHM_MBOX=qemu-bridge-hp-sram-mem
121			has_rom=true
122			;;
123		skl)
124			READY_IPC="00 00 00 f0"
125			SHM_IPC_REG="qemu-bridge-ipc(|-dsp)-io"
126			OUTBOX_OFFSET="7000"
127			SHM_MBOX=qemu-bridge-hp-sram-mem
128			has_rom=true
129			;;
130		kbl)
131			READY_IPC="00 00 00 f0"
132			SHM_IPC_REG="qemu-bridge-ipc(|-dsp)-io"
133			OUTBOX_OFFSET="7000"
134			SHM_MBOX=qemu-bridge-hp-sram-mem
135			has_rom=true
136			;;
137		cnl)
138			READY_IPC="00 00 00 f0"
139			SHM_IPC_REG="qemu-bridge-ipc(|-dsp)-io"
140			OUTBOX_OFFSET="5000"
141			SHM_MBOX=qemu-bridge-hp-sram-mem
142			has_rom=true
143			;;
144		icl)
145			READY_IPC="00 00 00 f0"
146			SHM_IPC_REG="qemu-bridge-ipc(|-dsp)-io"
147			OUTBOX_OFFSET="5000"
148			SHM_MBOX=qemu-bridge-hp-sram-mem
149			has_rom=true
150			;;
151		imx8 | imx8x | imx8m)
152			READY_IPC="00 00 00 00 00 00 04 c0"
153			SHM_IPC_REG=qemu-bridge-mu-io
154			SHM_MBOX=qemu-bridge-mbox-io
155			;;
156	esac
157
158	if $has_rom; then
159		ROM=(-r "${SOF_BUILDS}/build_${platform}_gcc/src/arch/xtensa/rom-$platform.bin")
160	fi
161
162        xtensa_host_sh=$(find_qemu_xtensa)
163
164	ret=0
165	( set -x
166
167	${xtensa_host_sh} "$PLATFORM" -k \
168	   "${SOF_BUILDS}"/build_"${platform}"_gcc/src/arch/xtensa/"$FWNAME" \
169                "${ROM[@]}" \
170		-o 2.0 "${SOF_BUILDS}"/dump-"$platform".txt
171	# dump log into sof.git incase running in docker
172	) || ret=$? # this defeats set -e
173	# See 'man timeout'
174	test $ret = 124 || die 'qemu failed before we stopped it!\n'
175
176	# use regular expression to match the SHM IPC REG file name, one of:
177	# /dev/shm/qemu-bridge-{shim,ipc,dsp}-io
178	SHM_IPC_REG_FILE=$(ls /dev/shm/ | grep -E $SHM_IPC_REG) || true
179
180	test -e /dev/shm/"${SHM_IPC_REG_FILE}" ||
181	    die '%s: %s not found in /dev/shm/\n' "$0" "$SHM_IPC_REG"
182
183	# Check if ready ipc header is in the ipc regs doorbell
184	# registers or shared memory for older platforms.
185	# See:
186	# - 'adsp_reg_space' in qemu/
187	# - shim_write() or ipc_write() in sof/
188	IPC_REG=$(hexdump -C /dev/shm/"$SHM_IPC_REG_FILE" |
189		      grep "$READY_IPC") || true
190
191	# Check if ready ipc message is in the mbox-io / sram-mem
192	# See "struct sof_ipc_fw_ready" and
193	# objdump -s -j .fw_ready -s build/sof
194	READY_MSG="6c 00 00 00 00 00 00 70"
195	IPC_MSG=$(hexdump -C /dev/shm/$SHM_MBOX | grep -A 4 "$READY_MSG" |
196		      grep -A 4 "$OUTBOX_OFFSET") || true
197
198	if [ "$IPC_REG" ]; then
199		echo "ipc reg dump:"
200		# directly output the log to be nice to look
201		hexdump -C /dev/shm/"$SHM_IPC_REG_FILE" | grep "$READY_IPC"
202		if [ "$IPC_MSG" ]; then
203			echo "ipc message dump:"
204			# directly output the log to be nice to look
205			hexdump -C /dev/shm/$SHM_MBOX | grep -A 4 "$READY_MSG" | grep -A 4 "$OUTBOX_OFFSET"
206		else
207			echo "Error mailbox failed"
208		fi
209	else
210		echo "Error ipc reg failed"
211	fi
212
213	if [[ "$IPC_REG" && "$IPC_MSG" ]]; then
214		echo "Boot success";
215	else
216		echo "Error boot failed"
217		tail -n 50 "${SOF_BUILDS}"/dump-"$platform".txt
218		exit 2;
219	fi
220done
221