Acer Iconia TAB A500 に Stock ROM 3.2 をインストール

基本的に個別の端末については言及しないつもりでいたのだが,ネタもないことであるし,これからは書いていくことにする。
A500 にはさまざまなカスタム ROM がでまわっているのでそれを使えばまぁそれほど不自由はない (らしい) のだが,システムがどのように構成されているのかということを捉えるうえでも*1日本版オフィシャル ROM 3.2 (Honeycomb) をインストールすることにする。

A500 のパーティション構成

たとえば下記の p1 に対応するブロックデバイスノードは /dev/block/mmcblk0p1 のようになる。実機が手元にないので間違っているかもしれない。

アップデータの抜き出し

システムアップデータのダウンロードをおこなう (そしてアップデータの適用まではおこなわない) と,/cache/fota_dn/ ディレクト*3以下に B992.....zip のような16進数の羅列のファイルが保存される。
末尾が zip であるが,実際には暗号化されたファイルとなっており,そのままでは zip アーカイバでは展開できない。
「暗号化」といっても単に全バイト 0x12 で XOR されているだけなので,たとえば下記のような簡単なプログラムで復号できる。

#include <stdio.h>

int main(int argc, char *argv[])
{
    int c;
    while ((c = getchar()) != EOF)
        putchar(c ^ 0x12);
    return 0;
}

復号したファイルを展開すると,中に update.zipAMSS.zip((AMSS.zip は現状ではダミーファイルとなっている。)) とほかいくつかのファイルがある。update.zipAndroid におけるいわゆる update.zip となっている。

公式 3.2 アップデートで注意が必要なところ

そもそも 3.2 にアップデートするためだけに update.zip を抽出する必要は本来はない。だが,公式版 3.2 にそのままアップデートすると下記のような弊害を生ずる。

  • (現時点で) 3.2 でブートした状態で root を取得する手段がない (ほんと?詳しくないからよく知らない)
  • ブートローダがインストールされてしまう
    • この新ブートローダでは公式の boot や recovery しかブートすることができない

update.zip に含まれる bootloader.blob というファイルが新ブートローダでのイメージであり,標準のアップデートスクリプトではこれが書きこまれてしまう((スクリプトでは /dev/block/mmcblk0p4 (/cache パーティション) に書き込んでいるが,おそらくそこに特定パターン (MSM-RADIO-UPDATE か?) のデータが書きこまれている場合,ブート時にブートローダに書きこむようになっているのだろう。))。

よって update.zipMETA-INF/com/google/android/updater-script に下記のようなパッチをあてる。

--- updater-script.orig
+++ updater-script
@@ -2,7 +2,6 @@
 format("ext4", "EMMC", "/dev/block/mmcblk0p3", "0");
 mount("ext4", "EMMC", "/dev/block/mmcblk0p3", "/system");
 mount("ext4", "EMMC", "/dev/block/mmcblk0p8", "/data");
-package_extract_dir("recovery", "/system");
 package_extract_dir("system", "/system");
 symlink("ash", "/system/bin/sh");
 symlink("toolbox", "/system/bin/cat", "/system/bin/chmod",
@@ -37,7 +36,6 @@
 set_perm(1002, 1002, 0440, "/system/etc/dbus.conf");
 set_perm(1014, 2000, 0550, "/system/etc/dhcpcd/dhcpcd-run-hooks");
 set_perm(0, 2000, 0550, "/system/etc/init.goldfish.sh");
-set_perm(0, 0, 0544, "/system/etc/install-recovery.sh");
 set_perm_recursive(0, 0, 0755, 0555, "/system/etc/ppp");
 set_perm_recursive(0, 2000, 0755, 0644, "/system/vendor");
 set_perm(0, 0, 0644, "/system/vendor/fake.txt");
@@ -54,8 +52,5 @@
 package_extract_dir("calibration", "/tmp/");
 run_program("/system/bin/sh", "/tmp/calibration.sh");
 package_extract_file("flexrom.img", "/dev/block/mmcblk0p6");
-package_extract_file("bootloader.blob","/tmp/bootloader.blob");
 unmount("/cache");
-format("ext4","EMMC","/dev/block/mmcblk0p4","0");
-run_program("/system/bin/dd","if=/tmp/bootloader.blob","of=/dev/block/mmcblk0p4");
 unmount("/system");
\ No newline at end of file

ついでに recovery パーティションの上書きを防ぐため,/system/etc/install-recovery.sh の駆動まわりも抑制してある。
個人的にはさらに /system/bin/su あたりも仕込んでおきつつ set_perm(0, 0, 04755, "/system/bin/su"); も追加した。
編集した後ふたたび update.zip にまとめなおして CWM recovery から適用した(update.zip の署名がベンダのものではなくなってしまうので,署名を無視することができる CWM など公式以外のリカバリからインストールする必要がある)。これで無事ブートローダはさわらずに 3.2 の stock ROM をインストールすることができた。

(旧) ブートローダについて

ブートローダでは boot パーティションや recovery パーティションの署名をチェックして,きちんと署名されていないイメージではブートできないようになっているらしい (伝聞*4 )。
ここでは 3.1 以前で利用されていた旧ブートローダについて解説する。

ブートローダは boot パーティションや recovery パーティションを読み込む際に,そのパーティションチェックサムを算出し,あらかじめ (/dev/block/mmcblk0p7 に) 格納されているチェックサムと異なる場合には,エラーを出して読み込まない (すなわちブートしない) ようになっている。
チェックサムアルゴリズムは不明だが,実はチェックサム格納エリアに「特殊なパターン」を書きこんでおくと,ブート時にブートローダパーティションチェックサムを算出し書きこんでくれるという (ある意味) 親切な設計になっていた (というのも,そもそも 3.1 以前の純正アップデータでもその機構を利用していたから)。
この機構を利用して,ブート時チェックサム自動計算モードにしてくれるプログラムがいわゆる「itsmagic」である (http://forum.xda-developers.com/showthread.php?t=1121543 参照)。
A500 用の CWM では,(カスタム) アップデータ適用時やリカバリ時などに自動的に itsmagic を実行してくれるので,現在ではユーザが意識して起動する必要はなくなっている (推測)。

itsmagic を解析したところ,「特殊なパターン」として /dev/block/mmcblk0p7 の 132 バイト目から 64 バイト分に

00 fb 30 94 99 01 4f 97 2e 4c 2b a5 18 6b dd 06

という16バイト×4 を書き込んでいるようだ (適当な解析結果なので間違っている可能性はある)。どのエリアがどのパーティションに対応しているのかはわからない。

おまけ

公式 3.2 にあげてしまった場合,http://forum.xda-developers.com/showthread.php?t=1276227 の手順に従えば旧来の ROM 等に戻すことができる,らしい。

  • 方法 1: APX モードに移行しホスト端末から (添付された) ファームウェアの書き込みを行う
    • APX モードでの書き込みには A500 の UID が必要 (lsusb -v 等で取得できる iSerial の値らしい)
  • 方法 2: 公式の鍵で署名された不安定な 3.0.1 firmware*5update.zip を一度適用して,そこから CWM の書き込みなりなんなりをおこなう

*1:まぁそれは建前で単にカスタム ROM を漁ったり入れ替えたりするのが面倒なだけだけど。

*2:後述するように p4 はブートローダのアップデート用にも用いられるようだ。

*3:ディレクトリ名はうろ覚えなので違うかも。

*4:http://forum.xda-developers.com/showthread.php?p=18522844#post18522844 参照

*5:公式の鍵で署名されていることから,おそらく純正 3.0.1 firmware updater にもブートローダが含まれていたのだろう。アップデータスクリプトをちらりとみてみたが,froyo 時代の標準アップデータスクリプトと異なり,リビジョンチェックをもともと行なっていないようで,公式 ROM でも ダウングレードできるようだ。