Android: 実機 Libero 003Z(ZTE Blade)の起動画面をカスタマイズ(3)

前回のブログに続き、今回はLibero 003Zの起動画面のカスタマイズ手順を具体的に書きます。

- 手順の概要 -
1) bootloader画面:splashパーティションの書き換え
2) init画面:bootパーティションの中のramdisk.imgの中の/logo.bmpの書き換え
3) bootanimation画面:/data/localの下にbootanimation.zipを作成
4) ホーム画面:/system/app/Launcher2.apkの中のリソースのイメージファイルを書き換え
 ( メニューにより壁紙にするのではなく、パッケージの書き換え)

この手順ではAndroidのテンポラリなroot権限で実行するコマンドがあります。root化については以下のページを参照して下さい。
  root化 → 実機でbash+BusyBox+su+Terminal Emulator+ssh

1) bootloader画面:

bootloaderは電源投入後に最初に起動されるプログラムで、デフォルトではbootパーティションの中のkernelを起動します。
fastbootモードで起動した場合はUSB経由でホストからの送信待ちになり、ホスト駆動型のfastbootプロトコルによりflashパーティションのwrite, eraseやデバイス情報の表示などができます。

fastbootモードで起動する方法
・adbコマンドを使用する方法
  adb -d reboot bootloader
・電源ボタンとボリュームボタンを使用する方法
  ネット上に、< VOL UP > & < POWER > という情報があったがうまくいかない。
  (以前やって、うまくいったような記憶もあり。。)

デバイス情報の表示例
$ fastboot getvar version
version: 0.5
finished. total time: 0.000s
$ fastboot getvar product
product: swordfish
finished. total time: 0.001s

bootloaderはデバイスによりgoogleの標準とは異なっている。003Zの場合はbootパーティション中のkernelを起動するか、あるいはfastbootモードにするかの切り替えの前に、画面イメージを表示しているように見える。画面イメージ部分はsplashパーティションの先頭から768072バイトであり、ヘッダが72バイト、画像データがRGB565フォーマットで480x800のBMP形式である。
(1ピクセル当たりRが5ビット、Gが6ビット、Bが5ビットで計16ビット(2バイト)。よって画像データのサイズは2x480x800=768000バイト。)
この起動イメージをGIMPで作成。GIMPで作成するとヘッダのサイズは70バイトになり全体で768070バイトになる。(この2バイトの差が何なのかは不明) 下記の手順では、logo-bootloader.bmpというファイル名にしています。
splashパーティションのサイズは1572864(16進数で180000)バイト。

$ cat /proc/mtd | grep splash
mtd2: 00180000 00020000 "splash"

先頭から768072バイト以降に何が入っているか、どのように使われているかわからなかったので(おそらく使われていない)現在の1572864バイトのデータのうち、先頭の768070バイトだけを書き換えた。

実行例)

[実機003Z上で]
# dd if=/dev/mtd/mtd2 of=/mnt/sdcard/mtd2-splash.img bs=4096
384+0 records in
384+0 records out
1572864 bytes transferred in 0.240 secs (6553600 bytes/sec)

[ホスト上で]
# adb -d pull /mnt/sdcard/mtd2-splash.img .
3389 KB/s (1572864 bytes in 0.453s)

# dd if=logo-bootloader.bmp of=mtd2-splash.img count=768070 bs=1 conv=notrunc
768070+0 records in
768070+0 records out
768070 bytes (768 kB) copied, 1.4897 s, 516 kB/s

# adb -d reboot bootloader

# fastboot flash splash mtd2-splash.img
sending 'splash' (1536 KB)...
OKAY [ 0.385s]
writing 'splash'...
OKAY [ 0.291s]
finished. total time: 0.676s

参考URL:
http://bootloader.wikidot.com/linux:boot:android

2) init画面:

googleの標準ではinitは起動すると/initlogo.rleに格納された画面イメージを表示します。
 → 起動画面のカスタマイズ(2) - initlogo.rle -
003Zではgoogle標準と違い、splashパーティションに格納されているのと同じBMP形式の/logo.bmpに格納された画面イメージを表示します。
画面イメージも同じものなので、起動画面を見ただけでは区別が付きません。なので今回はGIMPで画面イメージを作成する時に、splashパーティションに格納されるイメージ用はバックグラウンドを白っぽい色に、/log.bmp用は青い色にしてみました。

手順:

1. bootパーティションのイメージをファイルにコピー

[ 実機003Z上で ]
# dd if=/dev/mtd/mtd1 of=/mnt/sdcard/boot-dump.img bs=4096
1280+0 records in
1280+0 records out
5242880 bytes transferred in 1.333 secs (3933143 bytes/sec)

[ ホスト上で]
$ adb -d pull /mnt/sdcard/boot-dump.img .
3475 KB/s (5242880 bytes in 1.473s)

2. このファイルからカーネルと圧縮されたramdiskイメージを分離して取り出す

perlスクリプトsplit_bootimg.plを以下のURLからダウンロードして使いました。
http://code.google.com/p/zen-droid/downloads/detail?name=split_bootimg.p...

$ perl split_bootimg.pl boot-dump.img
Page size: 2048 (0x00000800)
Kernel size: 3200596 (0x0030d654)
Ramdisk size: 226339 (0x00037423)
Second size: 0 (0x00000000)
Board name: 
Command line: 
Writing boot-dump.img-kernel ... complete.
Writing boot-dump.img-ramdisk.gz ... complete.

$ ls
boot-dump.img  boot-dump.img-kernel  boot-dump.img-ramdisk.gz  split_bootimg.pl

3. 圧縮されたramdiskの中の/log.bmpを書き換え

$ gunzip boot-dump.img-ramdisk.gz
$ mkdir tmp
$ cd tmp
$ cpio -iI ../boot-dump.img-ramdisk
2208 blocks
$ ls
data          dev   init.blade.rc     init.qcom.rc  logo.bmp  sbin  system
default.prop  init  init.goldfish.rc  init.rc       proc      sys
$ cp < GIMPで作った新しい画面イメージ > logo.bmp

(ついでにPATHにbusyboxやbashを置いたディレクトリ/data/local/binを追加)
$ vi init.rc
export PATH /data/local/bin:/sbin:/system/sbin:/system/bin:/system/xbin

4. 新しい圧縮されたramdiskを生成

$ find | cpio -H newc -oO ../ramdisk.new
2208 blocks
$ cd ..
$ gzip ramdisk.new
$ ls
boot-dump.img  boot-dump.img-kernel  boot-dump.img-ramdisk  ramdisk.new.gz  split_bootimg.pl  tmp

5. カーネルと新しい圧縮されたramdiskから新しいbootパーティションのイメージを生成

mkbootimgコマンドは < ソースのルート >/out/host/linux-x86/bin/mkbootimgを使いました。

$ mkbootimg --kernel boot-dump.img-kernel --ramdisk ramdisk.new.gz --base 0x2600000 --pagesize 2048 --output boot-dump-new.img
$ ls -l boot-dump-new.img
-rw-r--r-- 1 user01 user01 3461120 12月 17 01:24 2011 boot-dump-new.img

参考:
mkbootimgのオプション--baseの値はカーネルのphysical load addr 0x02608000から0x8000を引いた値 0x2600000を指定する。
$ od -xc boot-dump.img | head -2
0000000    4e41    5244    494f    2144    d654    0030    8000    0260
          A   N   D   R   O   I   D   !   T 326   0  \0  \0 200   ` 002

下記、bootimg.hとbootimg.cの抜粋を参照。

6. fastbootコマンドにより新しいイメージをbootパーティションに書き込む

$ adb reboot bootloader
$ fastboot flash boot boot-dump-new.img
sending 'boot' (3380 KB)...
OKAY [  0.846s]
writing 'boot'...
OKAY [  0.691s]
finished. total time: 1.538s
$ fastboot reboot
rebooting...

finished. total time: 0.001s

参考URL:
http://d.hatena.ne.jp/urandroid/20110419/1303284666
HOWTO: Unpack, Edit, and Re-Pack Boot Images (Android-DLS Wiki)
参考ソース:

< ソースのルート >/system/core/mkbootimg/bootimg.h の抜粋
 23 #define BOOT_MAGIC "ANDROID!"
 24 #define BOOT_MAGIC_SIZE 8
 ...................
 28 struct boot_img_hdr
 29 {
 30     unsigned char magic[BOOT_MAGIC_SIZE];
 31 
 32     unsigned kernel_size;  /* size in bytes */
 33     unsigned kernel_addr;  /* physical load addr */
 34 
 35     unsigned ramdisk_size; /* size in bytes */
 36     unsigned ramdisk_addr; /* physical load addr */
....................
 52 /*
 53 ** +-----------------+ 
 54 ** | boot header     | 1 page
 55 ** +-----------------+
 56 ** | kernel          | n pages  
 57 ** +-----------------+
 58 ** | ramdisk         | m pages  
 59 ** +-----------------+
 60 ** | second stage    | o pages
 61 ** +-----------------+
 62 **
 63 ** n = (kernel_size + page_size - 1) / page_size
 64 ** m = (ramdisk_size + page_size - 1) / page_size
 65 ** o = (second_size + page_size - 1) / page_size
.........................

< ソースのルート >/system/core/mkbootimg/mkbootimg.c の抜粋
142         } else if(!strcmp(arg, "--base")) {
143             unsigned base = strtoul(val, 0, 16);
144             hdr.kernel_addr =  base + 0x00008000;
145             hdr.ramdisk_addr = base + 0x01000000;
146             hdr.second_addr =  base + 0x00F00000;
147             hdr.tags_addr =    base + 0x00000100;

3) bootanimation画面:

画面イメージのサイズを480x800で作った以外、手順はエミュレータの場合と同じ。
 → 起動画面のカスタマイズ(4) - bootanimation -

4) ホーム画面:

壁紙はアプリケーションLauncher2によって表示されています。ホーム画面の長押しからメニューで選択できる壁紙の候補となるイメージは/system/appの下にあるLauncher2のパッケージLauncher2.apkの中のリソースとして提供されています。この候補のイメージファイルの1つを書き換えてみました。(通常の壁紙の変更手順である、自分で用意したイメージファイルをメニューにより壁紙にする方法は、Launcher2パッケージの中身を書き換えることができないので、候補のイメージに入れることはできません。)
まず、画面2枚分のサイズの壁紙のイメージ(960x800)を用意しておきます。

以下、apkファイルをunzipで解凍し、zipで圧縮して結果としてはうまく行ったように見えます。しかし本来の正しい手順かどうか不明。

[ホスト上で]
$ adb -d pull /mnt/sdcard/Launcher2.apk .
3728 KB/s (13356445 bytes in 3.497s)
$ unzip Launcher2.apk
...........
  inflating: res/layout/wallpaper_item.xml  
  inflating: res/raw/allapps.rs      
  inflating: res/xml/default_workspace.xml  
 extracting: resources.arsc          
$ ls
AndroidManifest.xml  Launcher2.apk  META-INF  classes.dex  res  resources.arsc
$ ls res/drawable-hdpi/wallpaper*
res/drawable-hdpi/wallpaper1.jpg
res/drawable-hdpi/wallpaper1_small.jpg
........................
$ cp < 新しい壁紙ファイル > res/drawable-hdpi/wallpaper1.jpg
$ cp < 新しい壁紙ファイル(small) > res/drawable-hdpi/wallpaper1_small.jpg
$ zip  -r ../Launcher2.apk AndroidManifest.xml META-INF classes.dex res resources.arsc
............................
  adding: res/xml/default_workspace.xml (deflated 73%)
  adding: res/raw/ (stored 0%)
  adding: res/raw/allapps.rs (deflated 71%)
  adding: resources.arsc (deflated 70%)
$ adb -d push ../Launcher2.apk /mnt/sdcard
3687 KB/s (12496029 bytes in 3.309s)

[003Z上で]
# cp /mnt/sdcard/Launcher2.apk /system/app

これで、壁紙の選択候補に、入れ替えた新しい壁紙が表示される。