In the
first part, we learned how to repack official firmware from RUU format into the update package format, which gave us the opportunity to use the firmware we created without fear of overwriting the modified
recovery rom . And in the meantime, while HTC is
fighting with good resources , we will continue to study and improve the firmware.
In the previous part, even though we created a firmware that loads and works like a clock, we would like to extend the basic functionality of it. One of the most sought-after extensions is support for working with root privileges (
root ). Also here is the integration of
busybox . In addition, we will learn how to run arbitrary scripts at system startup and adapt
ramdisk to fit our needs.
Busybox
busybox is a
set of console unix utilities , focused on small size and performance, which is so important for mobile systems. Together with the
android system comes its own set of utilities - a
toolbox , which provides the minimum necessary functionality for the system, and as a result, is simpler in terms of quantity and function. The presence of
busybox in the system, on the one hand, will allow us, as developers, to feel more comfortable when working remotely on the device, on the other hand, will allow us to write complex scripts, and, for example, implement a mechanism to run our own scripts at boot time using
run-parts . Also it is worth considering that for some
android applications (especially those that use
root ) the presence of busybox is mandatory.
')
In order to simplify your life, we will use the already collected by the
busybox under our platform. For example, 1.16.0 from the well-known
modaco can be
picked up here . Whoever has the courage, and has too much time, can collect the busybox from the
official tree (a bit of the adaptation file for the Androids
toolchain , and the
bionic - android
libc implementation), or use
the XVilka assembly
instructions with
crosstool-ng and
uCLibc , or assemble from branches
cyanogenmod , where
bionic problems have already been solved.
So, before we add
busybox , we need to solve a few ideological points in the system:
- With the general scheme of using busybox / toolbox, we need to put the executable file and create links to it with the names of the applets . Links must be accessible from the $ PATH variable. Where to store links for busybox ? In / system / bin ? / system / xbin ? separate directory?
- Use pre-created links, or generate at the stage of installing the firmware?
In the example from the first part, we used the previously created links for the toolbox . But this option is difficult if firmware development is conducted on a Windows system, where there are certain problems with symbolic links. - Depending on the buildbox of busybox, we can override the set of commands that is already available in the toolbox . Who is more important?
On the one hand, busybox provides a wider functionality (as an example: the letter assignment of permissions for chmod ), but on the other hand, we may want to exclude already implemented utilities from busybox to reduce the size of the set.
To find out which
applets are supported by
busybox , just run it on the device with no parameters:
$ adb remount && adb push busybox / cache / $ adb shell chmod 0755 / cache / busybox $ adb shell / cache / busybox | tail tcpsvd, tee , telnet, telnetd, test , tftp, tftpd, time , timeout, top, touch , tr , traceroute, true , tty, ttysize, tunctl, udpsvd, umount , uname , uncompress, unexpand, uniq , unix2dos, unlzma, unlzop, unzip , uptime , usleep, uudecode, uuencode, vconfig, vi , vlock, volname, watch, watchdog, wc , wget , which , who , whoami , xargs , yes , zcat , zcip
$ adb remount && adb push busybox / cache / $ adb shell chmod 0755 / cache / busybox $ adb shell / cache / busybox | tail tcpsvd, tee , telnet, telnetd, test , tftp, tftpd, time , timeout, top, touch , tr , traceroute, true , tty, ttysize, tunctl, udpsvd, umount , uname , uncompress, unexpand, uniq , unix2dos, unlzma, unlzop, unzip , uptime , usleep, uudecode, uuencode, vconfig, vi , vlock, volname, watch, watchdog, wc , wget , which , who , whoami , xargs , yes , zcat , zcip
$ adb remount && adb push busybox / cache / $ adb shell chmod 0755 / cache / busybox $ adb shell / cache / busybox | tail tcpsvd, tee , telnet, telnetd, test , tftp, tftpd, time , timeout, top, touch , tr , traceroute, true , tty, ttysize, tunctl, udpsvd, umount , uname , uncompress, unexpand, uniq , unix2dos, unlzma, unlzop, unzip , uptime , usleep, uudecode, uuencode, vconfig, vi , vlock, volname, watch, watchdog, wc , wget , which , who , whoami , xargs , yes , zcat , zcip
$ adb remount && adb push busybox / cache / $ adb shell chmod 0755 / cache / busybox $ adb shell / cache / busybox | tail tcpsvd, tee , telnet, telnetd, test , tftp, tftpd, time , timeout, top, touch , tr , traceroute, true , tty, ttysize, tunctl, udpsvd, umount , uname , uncompress, unexpand, uniq , unix2dos, unlzma, unlzop, unzip , uptime , usleep, uudecode, uuencode, vconfig, vi , vlock, volname, watch, watchdog, wc , wget , which , who , whoami , xargs , yes , zcat , zcip
$ adb remount && adb push busybox / cache / $ adb shell chmod 0755 / cache / busybox $ adb shell / cache / busybox | tail tcpsvd, tee , telnet, telnetd, test , tftp, tftpd, time , timeout, top, touch , tr , traceroute, true , tty, ttysize, tunctl, udpsvd, umount , uname , uncompress, unexpand, uniq , unix2dos, unlzma, unlzop, unzip , uptime , usleep, uudecode, uuencode, vconfig, vi , vlock, volname, watch, watchdog, wc , wget , which , who , whoami , xargs , yes , zcat , zcip
$ adb remount && adb push busybox / cache / $ adb shell chmod 0755 / cache / busybox $ adb shell / cache / busybox | tail tcpsvd, tee , telnet, telnetd, test , tftp, tftpd, time , timeout, top, touch , tr , traceroute, true , tty, ttysize, tunctl, udpsvd, umount , uname , uncompress, unexpand, uniq , unix2dos, unlzma, unlzop, unzip , uptime , usleep, uudecode, uuencode, vconfig, vi , vlock, volname, watch, watchdog, wc , wget , which , who , whoami , xargs , yes , zcat , zcip
$ adb remount && adb push busybox / cache / $ adb shell chmod 0755 / cache / busybox $ adb shell / cache / busybox | tail tcpsvd, tee , telnet, telnetd, test , tftp, tftpd, time , timeout, top, touch , tr , traceroute, true , tty, ttysize, tunctl, udpsvd, umount , uname , uncompress, unexpand, uniq , unix2dos, unlzma, unlzop, unzip , uptime , usleep, uudecode, uuencode, vconfig, vi , vlock, volname, watch, watchdog, wc , wget , which , who , whoami , xargs , yes , zcat , zcip
$ adb remount && adb push busybox / cache / $ adb shell chmod 0755 / cache / busybox $ adb shell / cache / busybox | tail tcpsvd, tee , telnet, telnetd, test , tftp, tftpd, time , timeout, top, touch , tr , traceroute, true , tty, ttysize, tunctl, udpsvd, umount , uname , uncompress, unexpand, uniq , unix2dos, unlzma, unlzop, unzip , uptime , usleep, uudecode, uuencode, vconfig, vi , vlock, volname, watch, watchdog, wc , wget , which , who , whoami , xargs , yes , zcat , zcip
For a list of available applets for the
toolbox, we will focus on those links that were created in the original firmware.
- $ find habrrom / system / bin / -type l -printf '% f,' | tail
- getprop, insmod, ifconfig , setprop, wipe, watchprops, log, sync , schedtop, ioctl, rm ,
- sleep , notify, sendevent, dmesg , df , route, vmstat , mv , iftop, rmmod,
- dd , renice, kill , mount , start, rmdir , ps , ln , cmp , dumpcrash, top, getevent,
- umount , mkdir , setconsole, printenv, newfs_msdos, chown , cat , hd, chmod , date ,
- stop, smd, netstat , ls , lsmod , id ,
The only link pointing
not to the
toolbox is
dumpcrash :
- $ ls -o habrrom / system / bin / | grep dumpstate
- lrwxrwxrwx 1 astar 9 2010 -06- 16 03: 59 dumpcrash - > dumpstate
- -rwxr-xr-x 1 astar 14296 2010 -06- 16 03: 55 dumpstate
This is also worth considering when building the update script.
Suppose we decided that the main thing we will have is
busybox . I found that the following
toolbox applets
are unique:
getevent, getprop, iftop, ioctl, log, newfs_msdos, notify, schedtop, sendevent, setprop, smd, start, stop, top, umount , vmstat , watchprops, wipe
getevent, getprop, iftop, ioctl, log, newfs_msdos, notify, schedtop, sendevent, setprop, smd, start, stop, top, umount , vmstat , watchprops, wipe
And suppose that we want to create links during the installation of the firmware, for this we need to add the following lines to the update script:
- symlink dumpstate SYSTEM: bin / dumpcrash
- #
- symlink toolbox SYSTEM: bin / getprop
- # repeat the procedure for the necessary toolbox applets
- symlink busybox SYSTEM: xbin / [
- # repeat procedure for all busybox applets
Do not forget to remove links from the firmware itself.
$ rm ` find habrrom / system / bin / -type l `
Plus, we need to set the correct rights to
busybox.set_perm 0 0 04755 SYSTEM:xbin/busybox
Let's try to complicate your task. Let's place links for
busybox in a separate directory, for example
/ system / xbin / bb . To do this, we need to add a
non-empty folder in the firmware structure (an empty folder, will refuse to copy the update script):
- $ mkdir habrrom / system / xbin / bb
- $ touch habrrom / system / xbin / bb / placeholder
Now we can safely place our links to the specified path, for which we will update the update script:
- symlink ../busybox SYSTEM: xbin / bb / [
- # and so on
Ramdisk modification
However, simply placing the links in a separate folder is not enough. We need to expand the search path for executable files for the system. To do this, we need to add the $ PATH variable, which in the case of the android on HTC Hero is defined in
/init.rc- $ adb shell cat /init.rc | grep "export PATH"
- export PATH / sbin: / system / sbin: / system / bin: / system / xbin
All files in the root directory are part of
ramdisk (as well as some other subdirectories). Let's use the knowledge from the
first part : unpack the
boot , after which we can change the
PATH variable
- $ cat habrrom.boot / ramdisk / init.rc | grep "export PATH"
- export PATH / sbin: / system / sbin: / system / bin: / system / xbin: / system / xbin / bb
Before we collect
ramdisk back, let's do some more useful things.
To simplify life, we would like to have the following:
- The ability to mount the file system with write permissions
- USB debugging enabled by default. Otherwise, if something goes wrong, we will not be able to get at least some useful information about the causes, since the adbd service will be disabled and, as a result, adb logcat will be unavailable during the download.
- Run arbitrary scripts when the system boots (the most popular use cases are: enable app2sd , transfer dalvik-cache to / cache )
To do this, look at
/default.prop , which among other things stores the following settings:
- ro.secure - is used here and there throughout the system, but of the properties of interest to us, it includes adb remount to write a, and also, adb shell is executed with superuser privileges. Set the value to 0
- persist.service.adb.enable - is responsible for starting the adbd service, which helps us to perform remote interaction with the phone via the adb tool. Exhibiting at 1
Initialization scripts
To implement the third item, we need to modify the initialization script
/init.rc . This script as usual, is a
bike of your own android script on Android Init Language . I propose
to familiarize with the format
in the source code android . We are also interested in the ability to add our own
service (we cannot add our commands directly to the trigger, because there the command set is strictly limited):
service sysinit /system/bin/logwrapper /system/xbin/busybox run-parts /system/etc/init.d disabled oneshot
service sysinit /system/bin/logwrapper /system/xbin/busybox run-parts /system/etc/init.d disabled oneshot
service sysinit /system/bin/logwrapper /system/xbin/busybox run-parts /system/etc/init.d disabled oneshot
Those. we called our service
sysinit , which, when it starts, will run run-parts /system/etc/init.d, which in turn will run all the scripts from the corresponding folder in alphabetical order. we need
logwrapper in order to redirect the output instead of
/ dev / null (by default) to the logging system (accessible by
logcat ).
It remains to start our service (the option is
disabled , it says that this service will not start automatically). To do this, move the last command from the
on boot trigger to our own trigger for the end of the scripts and call our service.
- # not now
- # class_start default
- start sysinit
- on property: habr.sysinit.done = 1
- # now
- class_start default
We will also create two simple scripts in
/system/etc/init.d to demonstrate that this all works. The first one will do the standard
echo (
Hello World!, As without it), and the second will clear the cache, and inform the
init script that we have already finished and we can continue to load further.
- $ cat habrrom / system / etc / init.d / 00banner
- #! / system / bin / sh
- echo "Hello habrahabr!";
- $ cat habrrom / system / etc / init.d / 99complete
- #! / system / bin / sh
- sync;
- setprop habr.sysinit.done 1
And the final touch - we will install them the right to run (all the same - in the firmware update script)
set_perm_recursive 0 2000 0755 0755 SYSTEM:etc/init.d
Superuser rights Root.
For many, probably the most pressing question. For those patient who read it.
Despite the fact that the source
has its own implementation of su , it does not suit us, because its main goal is to launch applications as a superuser (or from
adb shell ) with the rights of other
user s.
We will use the
development of ChainsDD -
Superuser 2.1 application. The essence of the application is similar to the familiar
sudo , or even
Admin Approval Mode from the Windows system. If the application wants to elevate its rights to superuser rights (and not only), permission is requested from the user. You can also remember the accepted rule and automatically apply to all future calls.
We use the already
assembled application for Android 2.1, although there is always the opportunity to study and compile
most of the sources .
The application consists of two components:
- native module su . Which, when requesting a change of rights, redirects the request to its own Activity and waits for the user to respond
- Superuser.apk application - a set of interfaces ( Activity ) responsible for user interaction, storage of settings.


In order to add the specified functionality to our firmware - we will add modules to the appropriate sections of the system,
- $ cp su habrrom / system / xbin /
- $ cp Superuser.apk habrrom / system / app /
and configure permissions for the executable file (plus a link to
/ system / bin / , since some applications may call
su in an absolute path)
symlink ../xbin/su SYSTEM:bin/su set_perm 0 0 06755 SYSTEM:xbin/su
symlink ../xbin/su SYSTEM:bin/su set_perm 0 0 06755 SYSTEM:xbin/su
That's all.
I am enclosing a
small archive , as a final summary of what has been done in this article. Scripts,
busybox ,
Superuser, and more. For the curious.
This time it turned out to be somehow very Linux-like, and dumb. But next time we consider the topic more fun - repackaging system applications. In the meantime, the final point:

In previous and future series
- Part 1. Creating firmware in update.zip format based on RUU. Unpacking / packing boot. Update script. Sign service pack and applications.
- Part 2. Adding busybox. Adding root. Mount to write. Initialization script Editing ramdisk.