今天我拿到了一只新的手机,www.caocong.net手机上运行的正是大家所熟悉 Android 系统。我的任务是将 Firefox OS 移植到这一只新的手机上,这个工作对我来说非常有趣,因为通过 hacking 的方式可以让我更了解 Firefox OS 这个火红的操作系统。以下将分几个部份来逐步地描述 hacking 的过程。
取得 Firefox OS 的环境
取得Firefox OS 的环境非常容易,你只要在网络上申请一个 git 的公开帐号,即可通过以下的连结取得整个 Firefox OS 的环境。
https://github.com/mozilla-b2g/B2G
在这个连结中,Mozilla 也写了简单的步骤来引导我们如何在电脑中建立 Firefox OS 的环境。
对 boot.img 进行 hacking
Hacking boot.img 的目地是要进一步地取得 boot.img 里的 ramdisk.img 并对其作一些 hacking 的操作。通过 unbootimg/mkbootimg,可以轻易地将 boot.img 作 packing/unpacking。
对 ramdisk.img 进行 hacking 的操作
Ramdisk.img 所包含的是一个基本的 file system,在 kernel boot process 的过程中是首先被挂载起来的一个 file system,这里面也包含了 init.rc 的 shell script file。Boot.img unpacking 后的 ramdisk.img 是 gzip 档的格式,利用 gzip 解开之后再利用 cpio 作解压缩,即可以看到真正的 file system。当 init program 在启动的过程中,会 parsing init.rc 并根据 init.rc 的内容启动所有的 process 以及 daemon。因此,可以将 b2g以及其所需要的 library 放进 init.rc 中以便让系统在开机时自动启动。
当然,原生系统 user space 的启动也要从 init.rc 里拿掉。以下有两个主要的应用程序一定要从原生系统中移除。
Android 是通过 Zygote 来启动所有的应用程式,所以它是第一个要被移除掉的应用程序;
另外,由于 Firefox OS 已经整合了 Display 系统,因此需要将 Android 的 surfaceflinger 应用程序拿掉
将 adb 的权限改为 root
可以通过修改 default.prop 里的值可以完成这件事。default.prop也是在 ramdisk.img 中。下面连结中的文章有较详细的说明。
http://www.360doc.com/content/12/0223/17/11192_189061561.shtml
Android adb root权限 ? 就爱linux
修改./default.prop
把ro.secure设为0,persist.service.adb.enable设为1,adbd进程就会以root用户的身份启动。
原理:
可以看一下Android系统根目录下的/init.rc的片段:
… …
# adbd is controlled by the persist.service.adb.enable system property
service adbd /sbin/adbd
disabled
# adbd on at boot in emulator
on property:ro.kernel.qemu=1
start adbd
on property:persist.service.adb.enable=1
start adbd
on property:persist.service.adb.enable=0
stop adbd
… …
这里定义了一个触发器,只要persist.service.adb.enable值被置为1,就会启动/sbin/adbd。
在build目录下搜索一下,发现了main.mk中有这样的代码片段
## user/userdebug ##
user_variant := $(filter userdebug user,$(TARGET_BUILD_VARIANT))
enable_target_debugging := true
ifneq (,$(user_variant))
# Target is secure in user builds.
ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1
tags_to_install := user
ifeq ($(user_variant),userdebug)
# Pick up some extra useful tools
tags_to_install += debug
else
# Disable debugging in plain user builds.
enable_target_debugging :=
endif
# TODO: Always set WITH_DEXPREOPT (for user builds) once it works on OSX.
# Also, remove the corresponding block in config/product_config.make.
ifeq ($(HOST_OS)-$(WITH_DEXPREOPT_buildbot),linux-true)
WITH_DEXPREOPT := true
endif
# Disallow mock locations by default for user builds
ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=0
else # !user_variant
# Turn on checkjni for non-user builds.
ADDITIONAL_BUILD_PROPERTIES += ro.kernel.android.checkjni=1
# Set device insecure for non-user builds.
ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=0
# Allow mock locations by default for non user builds
ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=1
endif # !user_variant
ifeq (true,$(strip $(enable_target_debugging)))
# Target is more debuggable and adbd is on by default
ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=1 persist.service.adb.enable=1
# Include the debugging/testing OTA keys in this build.
INCLUDE_TEST_OTA_KEYS := true
else # !enable_target_debugging
# Target is less debuggable and adbd is off by default
ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=0 persist.service.adb.enable=0
endif # !enable_target_debugging
这段代码我大致解释一下:
主要通过判断当前的编译模式来给几个属性赋予不同的值,然后把属性存储在ADDITIONAL_DEFAULT_PROPERTIES这个变量中, 这个变量在后面是要写到根目录下的/default.prop中去,在系统启动时被属性服务加载的。也就是说我们在/default.prop中看到的几 个属性的值是在这里设置的。
只看两个属性ro.secure,persist.service.adb.enable。当前是user模式的话,编译系统会把 ro.secure置为1,把persist.service.adb.enable置为0.也就是说,用user模式编译出来的系统运行在安全模式 下,adbd默认关闭。即使通过设置属性的方式打开,adbd进程的用户也是shell,不具有root权限。这样,普通用户或者开发者拿到一个机器后, 通过PC运行adb shell时,是以shell用户登录机器的。
好了,现在把ro.secure置为0,再重新编译,只要设置属性persist.service.adb.enable的值为1,adbd进程就会以root用户的身份启动。
一旦将 adb 的权限改为 root,即可通过 adb 在 run time 的情况下去 hacking 手机里所有会使用到的 library
当上述的动都完成了之后,即可再利用cpio、gzip以及mkbootimg再压缩成一个开机时 adb 具有 root 权限的一个 boot.img.
Firefox OS 启动流程
基本上可以通过手动的方式启动,而这也是比较快的一条路。当与 Device 的 adb 建立连线之后,将以下几个 bins 以及 libraries push
$ adb push /system/b2g/ /system/b2g/
$ adb push /system/bin/b2g.sh /system/bin/
$ adb push /system/bin/rilproxy /system/bin/
$ adb push /system/bin/fakeperm /system/bin/
复制代码
另外,在 Firefox OS 的环境的根目录里执行以下两个指令
$ ./flash.sh gecko
$ cd gaia
$ make install-gaia
复制代码
在 /system/b2g 里放着 b2g 这个主要的 process 以及一些 preloaded 的 library,执行 b2g.sh 这个 script file 可以启动 rilproxy 以及 fakeperm 这两个行程。而 “./flash.sh gecko”以及 “make install-gaia”则是载入 gecko 以及 gaia 的主体。
Firefox OS hacking 过程所遇到的一些问题
当 b2g 已经可以成功的运行起来后,接下来就是在开机过程中 driver 在执行载入时会出现的问题了。至于这个部份,就要根据实际情况来分析了。以下几个步骤是我所遇到的问题,提供给大家参考。
在 adb log 中看到了 “display hardware composer error”,此时可以试着把原生的 library 以及 bin file 拿掉。
rild 无法 launch 起来。此时可以检查 system/build.prop 里 rild.libpath 所指到的 shared library 以及其需要的 shared library是否完整。
wifi 无法启动,可以试着置换 Firefox OS 所产生的 wpa_supplicant 以及 dhcpcd。另外这两个 bin file 的属性也需要注意。