Question:
How do I get the UART output from a baremetal program run with Qemu?
Background
Here is the command line invocation I have been using:
qemu-system-arm -M xilinx-zynq-a9 -cpu cortex-a9 -nographic -kernel $BUILD_DIR/mm.elf -m 512M -s -S
- using machine
xilinx-zynq-a9 - processor
cortex-a9 - as this is baremetal, the executable is a self contained ELF file
-m 512Msignifies the platform has 512 MiB of RAM-sis a shortcut for-gdb tcp::1234-Smeans freeze CPU at startup
The ELF file I am using (mm.elf) performs a simple matrix multiply operation, and then prints whether it succeeded or failed, and how long it took to run. The ELF was compiled using the Xilinx ARM toolchain. I am using this for software fault injection. Currently I use GDB to ask for the values of the variables which are supposed to be printed. However, as there are many things which could go wrong with printing in the context of fault injection, it would be nice to see what is actually sent over UART.
Related answers:
redirect QEMU window output to terminal running qemu
This has some suggestions I tried, but it isn't applicable because the question was about getting the Linux boot messages in the host terminal window.
How to run a program without an operating system?
This is one isn't very related because it still assumes that the user has a bootloader of some kind. While there must technically be a bootloader for the application to run at all, Xilinx provides this system code in files like boot.S, which are then compiled into the ELF file as code which runs before main.
Things that I have tried:
I tried adding each of these onto the end of my current Qemu command. The results follow the parameters tried.
-serial mon:stdio- nothing
-serial null -serial mon:stdio(because Cortex-A9 has two UARTs)- nothing
- the above two with
-semihostingadded- nothing
-serial stdio- cannot use stdio by multiple character devices
- could not connect serial device to character backend 'stdio'
-console=/dev/tty- invalid option
-curses- black screen, no output
Investigation
I looked at the disassembly of the ELF file and verified that the address to which the the UART messages are being written is the same as the Qemu setup expects (info mtree). Base address is 0xe0000000, the same in both places.
Goal
I want to be able to capture the output of messages sent to UART. If this is done by redirecting to stdout, that's fine. If it goes through a TCP socket, that's fine too. The fault injection setup uses Python, and Qemu is running as a subprocess, so it would be easy to get the output from either one of those sources.
Note: when run in the fault injection setup, the Qemu invocation is
qemu-system-arm -M xilinx-zynq-a9 -cpu cortex-a9 -nographic -kernel $BUILD_DIR/mm.elf -m 512M -gdb tcp::3345 -S -monitor telnet::3347,server,nowait
The main differences being 1) the GDB port number is different (so multiple instances can run simultaneously) and 2) Qemu is to be controlled using a telnet connection over a socket, so it can be controlled by the Python script.