Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| summerofcode2014:portingtoandroidemulator [2014/06/16 20:59] – AlexanderTarasikov | summerofcode2014:portingtoandroidemulator [2022/06/10 03:24] (current) – Link PeopleNames and use MailTo macro KubilayKocak | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ===== Porting FreeBSD to Android Emulator ===== | ===== Porting FreeBSD to Android Emulator ===== | ||
| - | * Student: astarasikov@%%FreeBSD%%.org | + | * Student: |
| - | * Mentor: | + | * Mentor: |
| ===== Project description ===== | ===== Project description ===== | ||
| + | |||
| Here I will describe the progress of porting %%FreeBSD%% to run on top of Android Emulator. | 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. | 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. | ||
| Line 11: | Line 12: | ||
| It's a fork of Qemu emulator with a new emulated %%SoC%% and a board called Goldfish. A somewhat nicer UI is also included. | 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 ===== | ===== Deliverables ===== | ||
| - | ==== Midterm ==== | ||
| - | | Check if timer is working fine | DONE | converted to 64-bit counter | | + | | Timer Driver |
| - | | Working PIC (Interrupt controller) | DONE | IRQs come to Framebuffer/ | + | | Working PIC (Interrupt controller) | DONE | works fine | |
| - | | ' | + | | ' |
| | Ethernet driver | DONE | It's SMSC91xx, just needed MMIO and IRQ setup | | | Ethernet driver | DONE | It's SMSC91xx, just needed MMIO and IRQ setup | | ||
| - | | Framebuffer driver | DONE | Implemented, | + | | Framebuffer driver | DONE | Implemented, |
| - | | NAND driver | TODO | See notes | | + | | MMC/SD card driver | DONE | |
| - | | Booting Root FS from NAND | TODO | Needs MTD device | + | | Booting Root FS from MMC | DONE | |
| + | | Prebuilt images for sharing | DONE | | ||
| + | | Events driver (virtual keyboard and touchscreen) | ||
| - | ==== Final ==== | + | ===== Milestones ===== |
| - | | Update to HEAD, push to SVN | TODO | | ||
| - | | 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 | * 19 May: Started coding, pushed a prototype of a kernel that boots and outputs to UART | ||
| * 23 June: Mid-term submission | * 23 June: Mid-term submission | ||
| Line 40: | Line 32: | ||
| * 18 August: hard deadline | * 18 August: hard deadline | ||
| - | ===== Notes for midterm | + | ===== The Code ===== |
| - | 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, | + | |
| - | 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. | + | The code is based off the ' |
| - | 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 " | + | <code> |
| + | svn co https:// | ||
| + | </ | ||
| - | Overall, the project turned out to be easier than planned since Android Emulator's Goldfish board is very similiar | + | I'm now preparing |
| - | 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 | + | <code> |
| - | + | git clone https:// | |
| - | ===== The Code ===== | + | cd freebsd |
| - | Currently the source code is at my github repo and I have some unpushed code since writing this page. I plan to push it to the %%GSoC%% SVN by the end of the week. | + | git checkout android_goldfish_arm_master |
| - | Use the **android_goldfish_arm_10.0.0** branch at the [[https:// | + | </ |
| ===== Useful Links ===== | ===== Useful Links ===== | ||
| Line 61: | Line 54: | ||
| ===== Caveats ===== | ===== Caveats ===== | ||
| - | Android Emulator supports ARMv5 (ARM926E) and ARM1136 cores, but not the coprocessor register instruction for domain control for these [[/SoCs|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 | + | |
| + | 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. | 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. | ||
| + | |||
| + | Most importantly - the emulator binaries from Android SDK contain a bug in MMU that does not occur in Linux but leads to data corruption in %%FreeBSD%% and being unable to boot kernel. To work around, you can use the prebuilt binaries from https:// | ||
| + | |||
| + | ===== How to compile Android Emulator on FreeBSD ===== | ||
| + | |||
| + | I have ported the Android Emulator source code to compile natively on %%FreeBSD%%. Currently graphics are broken but console works. I think it should be possible to have it fully working with minor patches. | ||
| + | |||
| + | < | ||
| + | git clone https:// | ||
| + | https:// | ||
| + | cd cd android_external_gtest | ||
| + | git checkout cm-11.0 | ||
| + | cd ../qemu.git | ||
| + | git checkout l-preview-freebsd | ||
| + | bash android-build-freebsd.sh | ||
| + | </ | ||
| ===== How to compile ===== | ===== How to compile ===== | ||
| - | Oh well, need to update with a script to build from an external directory | ||
| < | < | ||
| Line 81: | Line 90: | ||
| ==== How to build a qemu-compatible zImage ==== | ==== 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. | + | The same way as Versatile PB. |
| < | < | ||
| Line 99: | Line 108: | ||
| ==== How to run ==== | ==== How to run ==== | ||
| - | Create an Android Virtual device (install the SDK, run ' | + | |
| + | Create an Android Virtual device (install the SDK, run ' | ||
| Launch it from console specifying the avd name and the kernel file name (' | Launch it from console specifying the avd name and the kernel file name (' | ||
| Line 106: | Line 116: | ||
| emulator -shell-serial stdio -show-kernel -shell -avd FreeBSD | emulator -shell-serial stdio -show-kernel -shell -avd FreeBSD | ||
| </ | </ | ||
| + | |||
| + | You can get a prebuilt kernel from | ||
| + | https:// | ||
| + | |||
| + | You can use the rootfs from Raspberry Pi to test. For example, use the following SD Card image: | ||
| + | http:// | ||
| + | |||
| + | To test, add the "sd card" device to the android AVD. Then, go to " | ||
| + | |||
| + | ==== Debugging Bootup issues ==== | ||
| + | In this section I describe the approach I used for debugging the initialization | ||
| + | process of the %%FreeBSD%% kernel in Android Emulator (modified QEMU) on ARM. | ||
| + | |||
| + | ===== VM Setup ===== | ||
| + | |||
| + | I was using Mac OS X 10.9.4 as a Host OS, and I was using %%FreeBSD%% 10.0 in | ||
| + | a [[/ | ||
| + | to bridge the virtual network adapter with my [[/ | ||
| + | My workflow was the following: | ||
| + | I logged into the VM by SSH, launched the compilation, | ||
| + | compiled kernel and debugging symbols to a directory in a Host OS. Then, I | ||
| + | launched the Android Emulator in the Host OS. | ||
| + | |||
| + | In the subsequent sections, the following conventions are used: | ||
| + | VM IP Address -> 192.168.1.99 | ||
| + | Working directory in the Host OS -> / | ||
| + | VM %%RootFS%% mounted to Host OS -> / | ||
| + | |||
| + | ===== GDB Tricks ===== | ||
| + | |||
| + | I have chosen the following approach to debugging: use QEMU's GDB server | ||
| + | and a GDB from a cross-compiler toolchain. I confess I was a bit lazy | ||
| + | and decided not to build GDB in %%FreeBSD%%, | ||
| + | (on both Linux and Mac OS X). | ||
| + | |||
| + | I also mounted the %%FreeBSD%% root file system from the VM via the sshfs. The primary | ||
| + | reason to do so was to allow GDB to find sources (note that we need to use | ||
| + | substitute-path to convert absolute paths to our local mount path). Besided, | ||
| + | it allows to use a GUI text editor which in the Host OS, which may be considered | ||
| + | useful by some people. | ||
| + | |||
| + | I used the following script (which I named fbsd.gdb) for the GDB and I invoked GDB as | ||
| + | arm-none-eabi-gdb -x fbsd.gdb. | ||
| + | |||
| + | < | ||
| + | sshfs 192.168.1.99:/ | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | target remote tcp::1234 | ||
| + | add-symbol-file ./ | ||
| + | set substitute-path / / | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | scp 192.168.1.99:/ | ||
| + | scp 192.168.1.99:/ | ||
| + | killall -9 emulator || true | ||
| + | emulator -shell-serial stdio -show-kernel -shell -avd FreeBSD | ||
| + | </ | ||
| + | |||
| + | ===== Increasing Boot Verbosity ===== | ||
| + | |||
| + | One problem that I've faced is no matter how many options I enable | ||
| + | (DDB, KDB, GDB, VERBOSE_SYSINIT), | ||
| + | were printed as hex addresses instead of symbol name strings. | ||
| + | |||
| + | JFYI, I have pushed the relevant changes to https:// | ||
| + | |||
| + | Of course, it would be possible to use GDB to symbolize each address, | ||
| + | but that would be boring. So, I added a couple hacks to the kernel: | ||
| + | |||
| + | In kern/ | ||
| + | at function module_register_init, | ||
| + | echo the module name. | ||
| + | |||
| + | < | ||
| + | printf(" | ||
| + | </ | ||
| + | |||
| + | In kern/ | ||
| + | to make the kernel try to resolve the function name within all symbols. | ||
| + | |||
| + | In case the symbol is not resolved, I used the function db_printsym. | ||
| + | Unlike symbol_name (which used db_search_symbol), | ||
| + | performs a fuzzy lookup, so if the function pointer is not exactly at its | ||
| + | entry point, it will still print the function name and the offset unlike | ||
| + | db_search_symbol which will fail and result in printing the HEX address as is. | ||
| + | |||
| + | < | ||
| + | --- kern/ | ||
| + | +++ kern/ | ||
| + | @@ -263,14 +263,24 @@ | ||
| + | | ||
| + | |||
| + | | ||
| + | - DB_STGY_PROC); | ||
| + | + DB_STGY_ANY); | ||
| + | | ||
| + | | ||
| + | + | ||
| + | if (func != NULL && data != NULL) | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | + { | ||
| + | + printf(" | ||
| + | + db_printsym((vm_offset_t)(*sipp)-> | ||
| + | + printf(" | ||
| + | + db_printsym((vm_offset_t)(*sipp)-> | ||
| + | + printf(" | ||
| + | + } | ||
| + | + | ||
| + | + if (0) | ||
| + | # | ||
| + | | ||
| + | | ||
| + | </ | ||
| + | |||
| + | So, hex address like 0xc010a27c(0) becomes something like " | ||
| + | |||
| + | ---- | ||
| + | |||
| + | {{tag> | ||