Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| summerofcode2014:portingtoandroidemulator [2014/05/22 14:35] – AlexanderTarasikov | summerofcode2014:portingtoandroidemulator [2022/06/10 03:24] (current) – Link PeopleNames and use MailTo macro KubilayKocak | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | Here I will describe the progress of porting %%FreeBSD%% to run on top of Android Emulator. | + | ===== Porting |
| - | ===== Intro ===== | + | * Student: < |
| - | **Why?** | + | * Mentor: [[/ |
| - | Because | + | ===== 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' | **What' | ||
| Line 10: | Line 13: | ||
| 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. | ||
| - | ==== Caveats ==== | + | ===== Deliverables ===== |
| - | 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 | + | |
| + | | Timer Driver | DONE | converted to 64-bit counter | | ||
| + | | Working PIC (Interrupt controller) | DONE | works fine | | ||
| + | | ' | ||
| + | | Ethernet driver | DONE | It's SMSC91xx, just needed MMIO and IRQ setup | | ||
| + | | Framebuffer driver | DONE | Implemented, | ||
| + | | MMC/SD card driver | DONE | | ||
| + | | Booting Root FS from MMC | DONE | | ||
| + | | Prebuilt images for sharing | DONE | | ||
| + | | Events driver (virtual keyboard and touchscreen) | NOPE | | ||
| + | |||
| + | ===== Milestones ===== | ||
| + | |||
| + | * 19 May: Started coding, pushed a prototype of a kernel that boots and outputs to UART | ||
| + | * 23 June: Mid-term submission | ||
| + | * 11 August: ' | ||
| + | * 18 August: hard deadline | ||
| + | |||
| + | ===== The Code ===== | ||
| + | |||
| + | The code is based off the ' | ||
| + | |||
| + | < | ||
| + | svn co https:// | ||
| + | </ | ||
| + | |||
| + | I'm now preparing to merge it upstream. I keep a github branch which I regularly rebase against master and push cleaned-up code | ||
| + | |||
| + | < | ||
| + | git clone https:// | ||
| + | cd freebsd | ||
| + | git checkout android_goldfish_arm_master | ||
| + | </ | ||
| + | |||
| + | ===== Useful Links ===== | ||
| + | http:// | ||
| + | |||
| + | https:// | ||
| + | |||
| + | ===== 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. | 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 ==== | + | 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:// |
| - | Oh well, need to update with a script | + | |
| + | ===== How to compile | ||
| + | |||
| + | 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 | ||
| + | |||
| + | < | ||
| + | git clone https:// | ||
| + | https:// | ||
| + | cd cd android_external_gtest | ||
| + | git checkout cm-11.0 | ||
| + | cd ../ | ||
| + | git checkout l-preview-freebsd | ||
| + | bash android-build-freebsd.sh | ||
| + | </ | ||
| + | |||
| + | ===== How to compile ===== | ||
| < | < | ||
| Line 31: | 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 49: | 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 57: | Line 117: | ||
| </ | </ | ||
| - | ===== TODO ===== | + | You can get a prebuilt kernel from |
| - | * Check if timer is working fine | + | https://drive.google.com/ |
| - | * Working PIC (Interrupt controller) | + | |
| - | * Ethernet driver | + | |
| - | * MMC/SD card driver | + | |
| - | * Framebuffer driver | + | |
| - | * ' | + | |
| - | * Prebuilt images for sharing | + | |
| - | * Port %%FreeBSD%% a some real phone (if progress is done w/emulator by midterm). I'll be using a Nexus 5 phone with Qualcomm MSM8974 CPU | + | |
| - | ===== Useful Links ===== | + | You can use the rootfs from Raspberry Pi to test. For example, use the following SD Card image: |
| - | http://benno.id.au/blog/2007/11/29/android-qemu - Description | + | 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 -> /Users/alexander/ | ||
| + | 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: | ||
| + | </code> | ||
| + | |||
| + | < | ||
| + | target remote tcp::1234 | ||
| + | add-symbol-file ./kernel.debug 0xc0100000 | ||
| + | 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 | ||
| + | |||
| + | JFYI, I have pushed | ||
| + | |||
| + | 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(" module name=' | ||
| + | </ | ||
| + | |||
| + | 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), this function | ||
| + | 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> | ||