This is an old revision of the document!
Porting FreeBSD to Android Emulator
- Student: astarasikov@FreeBSD.org
- Mentor: gavin@freebsd.org
Project description
Here I will describe the progress of porting FreeBSD to run on top of Android Emulator. Android Emulator runs on a lot of platforms and is easy to set up. It can be therefore used as a unified platform for hacking FreeBSD on ARM.
What's Android Emulator?
It's a fork of Qemu emulator with a new emulated SoC and a board called Goldfish. A somewhat nicer UI is also included.
Approach to solving the problem
I plan to look into how linux drivers for the Goldfish board are implemented and write the corresponding analogues for the FreeBSD kernel.
Deliverables
Midterm
| Check if timer is working fine | DONE | converted to 64-bit counter |
| Working PIC (Interrupt controller) | DONE | IRQs come to Framebuffer/PDEV |
| 'pdev' driver (dynamic device detection) | WIP | See notes about FDT |
| Ethernet driver | DONE | It's SMSC91xx, just needed MMIO and IRQ setup |
| Framebuffer driver | DONE | Implemented, need working rootfs to test SYSCONS |
| Update to HEAD, push to SVN | DONE, boots. Needed a workaround for PERFCNT | |
| NAND driver | TODO | See notes |
| Booting Root FS from NAND | TODO | Needs MTD device |
Final
| Events driver (virtual keyboard and touchscreen) | TODO |
| MMC/SD card driver | TODO |
| Prebuilt images for sharing | TODO |
| Start porting FreeBSD to a Nexus 5 phone (with Qualcomm MSM8974 CPU) | TODO |
Milestones
- 19 May: Started coding, pushed a prototype of a kernel that boots and outputs to UART
- 23 June: Mid-term submission
- 11 August: 'Pencils down' date
- 18 August: hard deadline
Notes for midterm
PDEV is a virtual device available in the Android Emulator. Writing and reading its MMIO registers allows to get the list of available emulated devices such as framebuffer, NAND, MMC along with their MMIO address ranges and IRQ numbers. I am currenly not sure how one patches OpenFirmware Tree at runtime, so all the PDEV does is printing the list of devices to dmesg. On the other hand, it is unlikely that the MMIO ranges or IRQs change since they are hardcoded in the Emulator source code.
It turned out that the Emulator boots from an emulated NAND chip and MMC is only used for user data, so writing NAND driver is more important now if we want to build distributable images which can be run without additional setup.
Framebuffer driver should work, I have verified that it initializes and the screen turns white because the buffer is set with 0xff at the end of driver initialization. I was unable to test the virtual console (SYSCONS) though - if we put framebuffer on the FDT device buss, it will call “sc_attach_unit” early and this will result in a null pointer dereference inside SYSCONS code since no virtual console is yet installed. If we put it onto “sysbus” instead, the driver will get probed later, probably after rootfs is mounted. Since I do not have a working MTD driver yet, I have not tested it.
Overall, the project turned out to be easier than planned since Android Emulator's Goldfish board is very similiar to QEMU's VERSATILE which is supproted by FreeBSD, although as I predicted, more time was spent debugging various initialization issues rather than writing code.
I believe it would be good to cleanup cruft from such drivers such as SYSCONS (which leads to font output being copy-pasted into every framebuffer driver and many drivers consisting 70% of NO-OP function stubs) and identify other areas where it would be useful to provide a higher level of abstraction for SoC drivers. Therefore, if I have a booting userland on emulator by the end of first week of July, I plan to port FreeBSD onto a real phone, a Google Nexus 5. I believe certain areas which have been recently improved in Linux such as clock management, runtime PM, complex display ↔ GPU mappings, may need more attention in the FreeBSD kernel.
The Code
The code is based off the 'HEAD' version of FreeBSD cloned around the start of June. You can check it out via
svn co https://socsvn.freebsd.org/socsvn/soc2014/astarasikov
Useful Links
http://benno.id.au/blog/2007/11/29/android-qemu - Description of the emulated board (Goldfish). Oh, and the up-to-date emulator does not contain the mentioned bugs :)
https://android.googlesource.com/platform/external/qemu.git/+/master/docs/GOLDFISH-VIRTUAL-HARDWARE.TXT - documentation for the emulated hardware from Android Emulator
Caveats
Android Emulator supports ARMv5 (ARM926E) and ARM1136 cores, but not the coprocessor register instruction for domain control for these SoCs. Since we want to run on a vanilla emulator, let's just rely on the fact that the emulator also supports emulating ARM Cortex-A8 and only build FreeBSD for ARMv7
The latest version of Android Emulator is identical to QEMU in that it loads the kernel binary to 0x10000 (yes, 64K, not 1M) and jumps there. So let's just do what the versatilepb board does - link FreeBSD to 0x100000 (1M) and set up a trampoline. It should theoretically be possible to save some memory by linking to 0x10000 but I assume the kernel initially maps memory by 1M sections and that will fail unless additional patching is done.
How to compile
Oh well, need to update with a script to build from an external directory
#!/usr/local/bin/bash export TARGET=arm export TARGET_ARCH=armv6 export DESTDIR=/root/handhelds/arm export KERNCONF=GOLDFISH pushd . cd /usr/src/ make -j10 buildkernel KERNCONF=GOLDFISH popd
How to build a qemu-compatible zImage
Apprarently the same way as Versatile PB. Though, maybe this should be done by an LD script in kernel instead.
#!/bin/sh KERN=/usr/obj/arm.armv6/usr/src/sys/GOLDFISH/kernel.bin rm ./header rm ./flash /usr/bin/printf "\0\0\240\343" > header /usr/bin/printf "\0\020\240\343" >> header /usr/bin/printf "\0\040\240\343" >> header /usr/bin/printf "\0\060\240\343" >> header /usr/bin/printf "\001\366\240\343" >> header dd of=flash bs=1M count=4 if=/dev/zero dd of=flash bs=1 conv=notrunc if=header dd of=flash bs=64k oseek=15 conv=notrunc if=$KERN
How to run
Create an Android Virtual device (install the SDK, run 'android'). Be sure to select an ARMv7A target (basically, installing an SDK for Android 4.X will make ARMv7A the default target). Name your AVD (Android Virtual Device) 'FreeBSD' (though I assume it will work even if you call it 'Windows 8')
Launch it from console specifying the avd name and the kernel file name ('flash' in this case)
emulator -shell-serial stdio -show-kernel -shell -avd FreeBSD -kernel flash -qemu