QEMU ARM boot tags

I had to fight against a "feature" in QEMU today as I was screwing around. Normally when QEMU ARM boots a Linux kernel it sets up a tag list with all sorts of good information like available memory regions as explained here. This is the Linux’s standard for ARM and any ARM bootloader that loads Linux must do this. However, when I was booting my custom kernel with qemu-system-arm I discovered that R1 and R2 were empty upon boot using the switch -monitor stdio:

QEMU 0.13.0 monitor - type 'help' for more information
(qemu) info registers
R00=00000000 R01=00000000 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00000020
PSR=400001d3 -Z-- A svc32

This meant of course that the kernel refused to load at all. In addition, nowhere in memory could the tag list be found, as I saw with a quick assembly search through memory space.

So I downloaded the QEMU source code and found the relevant code in hw/arm_boot.c. The code there is pretty straightforward, and it turns out that QEMU ARM will only install a tag list if it determines kernel to be Linux. This is fine in itself, but the way it figures out if a given kernel is Linux is really stupid - as a comment in the file reads:

/* Assume that raw images are linux kernels, and ELF images are not.  */

This is really silly as one just objcopy -O binary any kernel into a raw image anyway. So I just set the initial assignment to is_linux = 1; in arm_load_kernel(…), compiled the ARM version, and copied it into my /usr/bin. Sigh.

About the author

I am a software engineer by profession and a passionate technology geek in my free time.