XEC Design >Mostly tutorials for Raspberry Pi


Working with QEMU

 This page will shows how to emulate an ARM1176JZF-S system. This is not meant to be a complete guide. Always refer to the manual.


  • A Linux environment
  • A compatible Linux kernel
  • QEMU
  • A root filesystem
  • A basic knowledge of the Linux command line
  • Ability to read and follow instructions carefully

Preparing the environment

  1. Create and enter the work directory.
  2. Move the rootfs file and linux kernel files to the working directory.
  3. All of the instructions will be carried out in this directory.

Starting QEMU

  • The main options are:
  1. -M versatilepb -cpu arm1176 -hda YOURROOTFSFILE -kernel YOURKERNELFILE -append "root=/dev/sda"
  • Click here to read about the Versatile platform.
  • The cpu option overrides the default arm926 with arm1176, which is used by Raspberry Pi.
  • Append is explained under kernel options.

Additional options:

To enable more than the default 128MB of RAM.

  1. -m x

where x is the amount of RAM desired (in MB).

  • To use an initial RAM disk:
  1. -initrd YOURINITRAMFS
  • To add additional disks:
  1. -hdb DISK2 -hdc DISK3 -hdd DISK4
  • To add a cdrom drive:
  1. -cdrom FILE
  • If graphic output is not needed, for example to emulate a headless raspi or to route the output directly to terminal (see 'Kernel options', 'console='):
  1. -nographic
  • To make QEMU to exit when the system reboots:
  1. -no-reboot

Kernel options

  • The linux kernel supports parameters as well. To pass these parameters, QEMU uses the '-append' option:
  1. -append "kernel options go here"
  • The most important parameter specifies which device to mount as the root filesystem:
  1. root=DEVICE
  • To specify which file to run once the kernel is loaded:
  1. init=FILE

Most of the time, this can be left out and the default works fine. If the default init script hangs, you can use init=/bin/sh to get a shell and fix the errors. A good initrd also helps in this scenario.

  • To prevent QEMU from simply freezing when the kernel panics (if your rootfs or kernel is not set up right):
  1. panic=x

Where x is the number of seconds before rebooting. This is useful with the -no-reboot QEMU option.

  • The default console device for the output can be specified.
  1. console=DEVICE

QEMU routes the host's console device to ttyAMA0 (if the -nographic option is used), so 'console=ttyAMA0' will output back to console rather than QEMU's window. This is useful if there's no X11 running or to log the boot-time output, which would normally scroll past. Works well with -nographic.


  • Start the kernel named zImage with two disks (rootfs.ext2 and secondfs.ext2), 256MB of RAM, exit and don't reboot on failure.
  1. qemu-system-arm -M versatilepb -cpu arm1176 -hda rootfs.ext2 -hdb secondfs.ext2 -no-reboot -kernel zImage -append "root=/dev/sda panic=1" -m 256
  • Disable graphic mode, boot zImage with rootfs.ext2, route the output to host's console, exit and don't reboot on failure.
  1. qemu-system-arm -M versatilepb -cpu arm1176 -hda rootfs.ext2 -nographic -no-reboot -kernel zImage -append "root=/dev/sda panic=1 console=ttyAMA0"

Disk images and file systems

  • A physical hard drive starts with 512 bytes of information (the MBR)  including a partition and code which loads a bootloader. The partition table contains information about how the data on the rest of the disc should be interpreted. A disk may have multiple partitions, so the partition table will let the computer know where each partition begins. These partitions contain file systems, which is what's of interest.


  • Since QEMU boots the kernel directly,  so there's no need to have a boot loader or the code from the MBR to start. Since there's only one partition, the partition table is not needed. By eliminating the need for the MBR, it's much easier to work with the file system without the preceding 512bytes. If multiple partitions are needed, multiple disks can be used instead.


  • QEMU supports multiple disk image formats, but the RAW format is most useful, because our host system sees it exactly the same way as the emulated system. This makes it easy to view and modify the file system content.

Creating and modifying disks


  • QEMU provides a tool called qemu-img to create disk images.
  1. qemu-img create FILENAME SIZE
  • The size can have optional suffixes:

'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)

  • The created files contain 0s and mean nothing to the system.
  • The disk image needs to be formatted to be usable:
  1. mkfs.ext2 FILENAME
  • For example, to create a 2GB EXT2-formatted, empty disk image named rootfs.ext2:
  1. qemu-img create rootfs.ext2 2G
  2. mkfs.ext2 rootfs.ext2
  • To modify an existing disk you can mount it directly onto a directory.
    • If the directory doesn't exist, create it:
      1. mkdir DIRECTORY
    • Mount:
  1. sudo mount DISKIMAGE DIRECTORY -t ext2 -o loop
  • The files inside the directory can now be modified.
  • Once the files are ready, the disk image should be unmounted before use:
  1. sudo umount DIRECTORY


  • SquashFS is a read-only archive. Changes made while booted from a SquashFS root are not saved, nor can the files be modified directly from the host system.
  • Install the necessary  tools to work with SquashFS:
  1. sudo apt-get install squashfs-tools
  • To extract:
  1. unsquashfs FILE
  • The files will be extracted to the ./squashfs-root directory where they can be modified.
  • To compress:
  1. mksquashfs DIRECTORY FILE
  • If FILE exists, the new files will be appended, should be avoided, unless you've read the SquashFS documentation and know what you're doing.


  • CPIO is also a read-only archive. It is used for initrd images.
  • Extracting:
    • Create and enter the directory where the files need to be extracted:
    1. mkdir DIRECTORY
    2. cd DIRECTORY
    • Extracting bz2 cpio archives:
    1. bzcat ../FILE |cpio -idv
    • Extracting gzip cpio archives:
    1. gzip -c -d ../FILE |cpio -idv
    • Extracting uncompressed cpio archives:
    1. cat ../FILE |cpio -idv
  • The files can now be modified.
  • Compressing:
  1. mkdir DIRECTORY
  3. find ./ | cpio -H newc -o | gzip > ../FILE



Everything works fine with -nographic, but when I boot using the SDL interface, I don't get a login prompt.

It is likely that your distro routed the login prompt to a different device (/dev/ttyS0, perhaps). Try adding console=tty0 to your -append string.


Filed under: QEMU Leave a comment
Comments (5) Trackbacks (5)
  1. It works in 64-bit Ubuntu 12.04 using your example at http://xecdesign.com/qemu-emulating-raspberry-pi-the-easy-way/ including newer 2012-12-16-wheezy-raspian.img. However, the newer rev 2.0 model B Raspberry Pi has 512 MB (typically minus default 64 MB gpu RAM or whatever specified in /boot/config.txt). And you give an example on this page using -m 512, but if I give it anything other than -m 256, it hangs at this point with just a dark QEMU window:

    Uncompressing Linux… done, booting the kernel.

    Would that have anything to do with boot messages when it does work with -m 256 saying that it cannot find “libkmod” because there is no module directory for the kernel-qemu version?

  2. Just curious — what is the reason for using the “-M versatilepb” option? Is the reason historical, since the Versatile platform seems to be obsolete?


    • That’s a good question. At the time the original tutorial was written, that’s the platform that seemed most stable, reflected the pi’s hardware and what the Pi foundation folks were using for testing as well. I’ll take a look at the other other options when I have some free time in a few weeks. It would be nice if there’s something with a better display, sound and more RAM.

  3. Hello

    I’ve been trying to emulate the MPC8544DS from Freescale. It is a powerpc machine. I was able to get it working with Qemu1.7 using the following command:

    qemu-system-ppc -M mpc8544ds -m 512 -kernel zImage -s -nographic -initrd busyboxfs.img -append “root=/dev/ram rdinit=/bin/sh

    where busyboxfs.img is a cpio archive and the kernel is a cross-compiled kernel (im using the embedian tool chain).

    However when I try to do this with the latest Qemu (v2.0.2) it just doesn’t show anything. I do not even know if it is booting and if it is, where is going bonkers…

    How do I see whats happening behind the scenes??

Leave a comment