パーティションとイメージ

パーティション

Android デバイスには、起動プロセスでさまざまな機能を果たす複数のパーティションが含まれています。A/B アップデートをサポートするために、デバイスには bootsystemvendorradio の各パーティションにつき 1 つのスロットが必要です。

  • boot: boot パーティションには、mkbootimg で結合されたカーネル イメージと RAM ディスクが含まれます。新しい boot パーティションをフラッシュせずに直接カーネルをフラッシュするために、以下の仮想パーティションを使用できます。
    • kernel: 仮想 kernel パーティションは、新しいイメージを古いイメージに書き込むことで、カーネル(zImage、zImage-dtb、Image.gz-dtb)のみを上書きします。これを行うには、eMMC で既存のカーネル イメージの開始位置を特定し、その場所にコピーします。その際、新しいカーネル イメージが既存のカーネル イメージより大きい可能性があることを考慮します。ブートローダーは、後続のデータを移動して空き容量を確保するか、エラーとともに処理を中止できます。提供された開発用カーネルに互換性がない場合、dtb パーティション(存在する場合)か、関連するカーネル モジュールがある vendor または system パーティションを更新する必要があります。
    • ramdisk: 仮想 ramdisk パーティションは、新しいイメージを古いイメージに書き込むことで、RAM ディスクのみを上書きします。このために、eMMC で既存の ramdisk.img の開始位置を特定し、その場所にコピーします。その際、新しい RAM ディスクが既存の RAM ディスクよりも大きい可能性があることを考慮します。ブートローダーは、後続のデータを移動して空き容量を確保するか、エラーとともに処理を中止できます。
  • system: systemパーティションには、主に Android フレームワークが格納されています。
  • recovery: recoveryパーティションには、OTA プロセス中に起動されるリカバリ イメージが格納されています。デバイスが A/B アップデートをサポートしている場合、recovery は個別のイメージではなく、ブートイメージに含まれる RAM ディスクの可能性があります。
  • cache: cache パーティションには、一時データが格納されています。デバイスが A/B アップデートを使用する場合、このパーティションは省略可能です。cache パーティションは消去可能であればよく、ブートローダーからの書き込みを可能にする必要はありません。サイズは、デバイスタイプと userdata の空き容量によって異なります。現在、50 MB~100 MB で問題ありません。
  • misc: misc パーティションはリカバリで使用されます。サイズは 4 KB 以上です。
  • userdata: userdata パーティションには、カスタマイズ データなど、ユーザーがインストールしたアプリケーションとデータが含まれます。
  • metadata: metadata パーティションは、デバイスが暗号化されている場合に使用されます。サイズは 16 MB 以上です。
  • vendor: vendor パーティションには、Android オープンソース プロジェクト(AOSP)に配布できないバイナリが含まれています。専有情報がない場合、このパーティションは省略可能です。
  • radio: radio パーティションには無線イメージが含まれます。このパーティションは、無線を含み、専用パーティションに無線固有のソフトウェアがあるデバイスにのみ必要です。
  • tos: tos パーティションには Trusty OS のバイナリ イメージが格納されます。デバイスに Trusty が含まれている場合のみ使用されます。

フロー

ブートローダーの動作は次のとおりです。

  1. 最初にブートローダーが読み込まれます。
  2. ブートローダはメモリを初期化します。
  3. A/B アップデートが使用される場合、現在のブートスロットを決定します。
  4. アップデートのサポートで説明されているように、代わりにリカバリモードで起動するかどうかを決定します。
  5. ブートローダーがイメージを読み込みます。このイメージにはカーネルと RAM ディスクが含まれます(Treble にはもっと含まれます)。
  6. ブートローダーは、自己実行型の圧縮バイナリとしてカーネルのメモリへの読み込みを開始します。
  7. カーネルは自己解凍し、メモリへの実行を開始します。
  8. その後、古いデバイスは init を RAM ディスクから読み込み、新しいデバイスは /system パーティションから読み込みます。
  9. /system から init が起動し、/vendor/oem/odm などの他のすべてのパーティションのマウントを開始します。その後、コードの実行を開始してデバイスを起動します。

イメージ

ブートローダーは、次のイメージに依存しています。

カーネル イメージ

カーネル イメージは、zImage、Image、Image.gz などの標準的な Linux 形式で作成されます。カーネル イメージは独立してフラッシュされ、RAM ディスク イメージと結合され、boot パーティションにフラッシュされるか、メモリから起動されます。カーネル イメージを作成する場合、デバイスツリーに別のパーティションを使用するよりも、連結されたデバイスツリー バイナリを使用することをおすすめします。複数のデバイスツリー Blob(DTB)を複数のリビジョンのボードで使用する場合は、ボードのリビジョンの降順に複数の DTB を連結します。

RAM ディスク イメージ

RAM ディスクには、rootfs としてマウントするのに適したルート ファイル システムを含める必要があります。 RAM ディスク イメージは、mkbootfs を使用してカーネル イメージと結合され、boot パーティションにフラッシュされます。

ブートイメージ

ブートイメージには、未修正の mkbootimg を使用して、カーネルと RAM ディスクを組み合わされた状態で含める必要があります。

mkbootimg 実装は system/core/mkbootimg にあります。

ブートローダーは、mkbootimg によって生成された bootimg.h ヘッダー ファイルを読み取り、カーネルのヘッダーを更新して、RAM ディスクの正確な場所とサイズ、カーネルのベースアドレス、コマンドライン パラメータなどを格納します。続いて、ブートローダーが生成したコマンドラインの末尾に、ブートイメージで指定されたコマンドラインを追加します。

ファイル システムのイメージ(system、userdata、recovery)

YAFFS2 イメージ形式

raw NAND ストレージを使用している場合、これらのイメージは YAFFS2 でなければならず、Android オープンソース プロジェクト(AOSP)の external/yaffs2/yaffs2/utils にある未修正の mkyaffs2image によって生成する必要があります。イメージの形式は次のとおりです。

    
    | 2k bytes of data| yaffs extra data | padding | | 0  2048 | 0 64 | variable|
    
    

ブートローダーはこれらのイメージを使用し、yaffs の余分なデータを、指定された nand ハードウェアの帯域外領域の適切な場所に再配置します。ソフトウェア ECC が必要な場合、ブートローダーはこの時点で計算も行う必要があります。

スパース イメージ形式

スパース イメージ形式がサポートされている必要があります。この説明はドキュメント「ext4 圧縮イメージ」と system/core/libsparse/sparse_format.h にあり、system/core/libsparse/sparse_read.cpp に実装されています。

ブロックベースのストレージ デバイスを使用する場合は、ext4 または f2fs がサポートされている必要があります。大容量の空の ext4 ファイル システム(userdata)をすばやく転送してフラッシュするには、ファイル システムの未書き込み領域の情報を含むイメージをスパース形式で格納します。このファイル形式は mke2fs によって記述されます。このユーティリティは、ブートローダーが読み取ってフラッシュするイメージのファイル形式の作成にも使用されます。属性については、以下のセクションをご覧ください。

ファイル形式
  • すべてのフィールドが符号なしリトル エンディアンである
  • ファイルにはファイル ヘッダーが含まれ、一連のチャンクが続く
  • ファイル ヘッダー、チャンク ヘッダー、チャンクデータの長さがすべて 4 バイトの倍数である
  • 32 ビットのマジック: 0xed26ff3a
  • 16 ビットのメジャー バージョン(0x1) - 上位のメジャー バージョンのイメージを拒否する
  • 16 ビットのマイナー バージョン(0x0) - 上位のマイナー バージョンのイメージを許可する
  • 16 ビットの、バイト単位のファイル ヘッダーサイズ(v1.0 では 28)
  • 16 ビットの、バイト単位のチャンク ヘッダーサイズ(v1.0 では 12)
  • 32 ビットの、バイト単位のブロックサイズ(4 の倍数にする必要がある)
  • 32 ビットの、出力ファイル内の合計ブロック数
  • 32 ビットの、入力ファイル内の合計チャンク数

32 ビットの、オリジナル データの CRC32 チェックサムでは、「don't care」を 0 標準 802.3 多項式としてカウントし、パブリック ドメイン テーブルの実装を使用します。

チャンク
  • 16 ビットのチャンク型:
    • 0xCAC1 raw
    • 0xCAC2 fill
    • 0xCAC3 don't care
  • 16 ビットは予約済み(0 として書き込み、読み取り時に無視)
  • 出力イメージ内の、32 ビットのブロック単位のチャンクサイズ
  • チャンク ヘッダーとデータを含む、32 ビットのチャンク入力ファイルの合計サイズ
データ
  • raw、raw データの場合、ブロック単位のサイズ * バイト単位のブロックサイズ
  • fill の場合、4 バイトの fill データ
ライターの実装

mke2fs ユーティリティは、イメージのどの領域に書き込む必要があるかをすでに認識しており、それらの領域の間に「don't care」チャンクをエンコードします。もう 1 つのツールである img2simg は、通常の(スパース以外の)イメージをスパース イメージに変換します。通常のイメージには「don't care」領域に関する情報はありません。変換を行うことで、繰り返しデータのブロックを検索し、最終的なイメージサイズを減らすことができます。

リーダーの実装

リーダーは、不明なメジャー バージョンのイメージを拒否し、不明なマイナー バージョンのイメージを受け入れる必要があります。リーダーは、サポートしていないチャンクサイズのイメージを拒否できます。

メジャー バージョンが検証されると、リーダーはタイプ フィールドが不明なチャンクを無視します。「chunk size in file」を使用してファイル内のチャンクをスキップし、出力の「chunk size in blocks」ブロックをスキップします。

巡回冗長検査 - 802.3 CRC32 - は、ディスクに書き込まれるデータについて計算されます。書き込みされていない領域(don't care またはスキップされたチャンク)は、CRC では 0 としてカウントされます。書き込まれた、またはスキップされたブロックの総数は、ヘッダーの「total blocks」フィールドと比較されます。 simg2img ツールは、スパース イメージ形式を標準イメージに変換し、これによりスパース情報が失われます。