Emulate a Raspberry Pi on your Mac

I've paused my work on Filament for a while to go back and do some more research into low level graphics for IdealOS. As part of that I wanted to emulate a Raspberry Pi on my Mac. The short version is: yes it can be done but it's useless for graphics.

The RaspberryPi is an ARM computer and most Macs (until a few months ago) are X86. That means I need an emulator, not just an OS conatiner wrapper like Docker. Fortunately the open source emulation tool QEMU is up to the task.

Following the instructions here, I was able to download and run QEMU on my Mac. The two scripts in this repo get the job done reliably. ./install.sh willl download QEMU, a Raspbian distro, and all of the required deps. Then ./run.sh will run it as a headless instance, giving me a bash shell into a virtual Pi. So far so good. But of course I want graphics.

Adding Graphics

I tried running the example command line graphics programs in /vc/opt but they wouldn't work, complaining that it can't access the vchiq. But I could have *sworn* I'd seen QEMU running a Raspbian desktop. How did they do it?

These instructions won't give me any graphics because it's using the 'lite' version of Raspbian which doesn't include a desktop and X11. So I modified the scripts to use raspbian-buster instead of raspbian-buster-lite, turn off the headless option, then ran the entire process again. (patches below). Then I was able to get X to boot:

z

WHAAA?!

So what's the deal? Why can X run but not the opengl samples?

After further research I've determined that QEMU emulates the main ARM CPU, but *not* the custom graphics chip in the Pi. That means I'll never get the hardware acceleration I need for testing IdealOS. X works because it's using the standard linux framebuffer, which is a minimal graphics structure in main memory that does no acceleration. Essentially it's just drawing into a chunk of memory and handing it to QEMU to draw to the real screen. This also explains why X under QEMU is *sooo slow*. Looks like I'll need a real Raspberry Pi for my experiments.

Here's the patches:

diff --git a/install.sh b/install.sh
index 62f3425..1f101ba 100755
--- a/install.sh
+++ b/install.sh
@@ -2,7 +2,7 @@

set -euxo pipefail

-readonly IMAGE='2020-02-13-raspbian-buster-lite'
+readonly IMAGE='2020-02-13-raspbian-buster'
readonly KERNEL='kernel-qemu-5.4.51-buster'
readonly PTB='versatile-pb-buster-5.4.51.dtb'

@@ -13,7 +13,7 @@ readonly PTB_FILE="${TMP_DIR}/${PTB}"
# commit hash to use for the https://github.com/dhruvvyas90/qemu-rpi-kernel/ repo:
readonly COMMIT_HASH='061a3853cf2e2390046d163d90181bde1c4cd78f'

-readonly IMAGE_URL="https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2020-02-14/${IMAGE}.zip"
+readonly IMAGE_URL="https://downloads.raspberrypi.org/raspbian/images/raspbian-2020-02-14/${IMAGE}.zip"
readonly KERNEL_URL="https://github.com/dhruvvyas90/qemu-rpi-kernel/blob/${COMMIT_HASH}/${KERNEL}?raw=true"
readonly PTB_URL="https://github.com/dhruvvyas90/qemu-rpi-kernel/blob/${COMMIT_HASH}/${PTB}?raw=true"

diff --git a/run.sh b/run.sh
index 73e9006..8909b80 100755
--- a/run.sh
+++ b/run.sh
@@ -2,7 +2,7 @@

set -euxo pipefail

-readonly IMAGE='2020-02-13-raspbian-buster-lite'
+readonly IMAGE='2020-02-13-raspbian-buster'
readonly KERNEL='kernel-qemu-5.4.51-buster'
readonly PTB='versatile-pb-buster-5.4.51.dtb'

@@ -30,8 +30,7 @@ run_qemu () {
-dtb "$PTB_FILE" \
-kernel "$KERNEL_FILE" \
-append 'root=/dev/vda2 panic=1' \
- -no-reboot \
- -nographic
+ -no-reboot
}
main () {
(END)

Talk to me about it on Twitter

Posted April 15th, 2021

Tagged: idealos