本文へ
Nonbiri

独立したデバイスサポート · MediaTek MT6789 / MT8781

MindOne

復元したデバイスツリーと 2 本のカーネル、そしてその上のユーザー空間。本来ベンダーが担うサポート一式を、外側から作って公開しました。

この端末が毎日動いているのは Linux 6.12 です。その手前の 6.1 の移植も、アーカイブとして隣に残しています。あわせてカーネル外のドライバツリーが 339、うち 290 モジュールが起動時に読み込まれ、デバイスツリーはコンパイル済みバイナリから読める形に復元しました。カーネルより上のクローズドな部分も一つずつオープンに書き直しています — 今のところ音声 HAL、センサー HAL、HIDL→AIDL ブリッジ 4 本。動いていても読めないバイナリは調整できず、作られた時点の Android から動けないからです。

進行中 · 最終更新

公開済み

この仕事が実際に何だったか

ソースが公開されていない端末は、ロックされた端末ではありません。ドライバを書かないかぎり、そもそもドライバが存在しない端末です。

ベンダーのカーネルソースも、デバイスツリーも、リファレンス BSP も、問い合わせ先すら、手に入るものは何一つありませんでした。土台は Google の Android Common Kernel、カーネル外のドライバは MediaTek がチップ向けに公開を義務づけられている GPL ソースから始めて、基板に合わせて一つずつ直しています。これが設定作業ではなくサポート一式である理由は、書かなければならなかった量にあります — 339 のドライバツリーのうち 172 に自前の修正が入り、10 個のモジュールはここにしか存在せず、デバイスツリーは他に読むものがないのでバイナリから解いてきました。

設定ではなく、書いたもの

代わりにあったのがバイナリだったので存在する 7 つ。出発点となるソースがそもそもなかったか、動いてはいるが手を入れられないベンダーのブロブがあったかのどちらかです。

01

デバイスツリー

18 の .dtsi と 1 つの .dts

端末自身の vendor_boot から取り出した出荷時 DTB — ソースではなくコンパイル済みバイナリ — を逆コンパイルし、クロック、pinctrl、レギュレータ、ディスプレイ、カメラ、音声、サーマル、予約メモリまでを読める .dts / .dtsi に組み直しました。dtc の警告はゼロ。2 本のカーネルで共有しています。

02

音声 HAL

1,800 行

MediaTek AFE 向けの完全なプライマリ HAL で、ベンダーのバイナリを包むのではなく置き換えるために書きました — そもそも音声経路に手が届くようになったのはそのおかげです。スピーカーのハイパスと共有リミッタはバイナリのままでは不可能な調整ですし、マイクはコーデックのデジタルマイク経路を有効にし、アナログ種別は触らない必要がありました。出荷時のミキサー設定では無音を録音して、エラーも出しません。

03

センサー HAL

2,400 行

ベンダー実装に代わるオープンな実装で、カーネルの hf_manager インターフェースに直結し、較正値は工場出荷時の nvcfg パーティションから読みます。2 本のワーカースレッドはいずれも実イベントで待つので、全センサーを切れば HAL はウェイクアップを一切起こしません — コードが自分のものになって初めて直せる類の話です。

04

HIDL→AIDL ブリッジ

2,100 行

指紋、gatekeeper、セキュアエレメント、テザリングオフロードの 4 つのサービスが、まだ書き直していないクローズドな HIDL HAL へ AIDL を橋渡しします。起動時に一度バインドして終わりではなく、相手が落ちても生き延びます。Android 16 の要件ではなく Android 17 への地ならし — ベンダーバイナリが想定していない VINTF レベルへ端末を動かせるのは、この継ぎ目があるからです。

05

カーネルモジュール 10 本

ベンダーに相当物なし

出荷時のテーブルが記述していなかったサーマルゾーン、復帰後に PMIC の割り込み有効化を張り直すガード、この基板固有のストレージと RF レギュレータの挙動、そして何度も役に立ったのでツリーに残した立ち上げ用の計測コード。

06

復元した musb ドライバ

挙動から再構築

MediaTek の USB コントローラドライバを組み直したものです。端末がまったくサスペンドできなくなる不具合を直します — ケーブルを抜くとガジェットの後片付けが切断処理より先に走り、ドライバ自身の解放経路に到達できないまま wakeup source が握られっぱなしになっていました。

07

モデム用ユーザー空間

10,000 行・未同梱

オープンな CCCI スタック — 起動時にモデムが必要とするファイルサービス、起動と状態管理のデーモン、RPC デーモン、ライン規律の多重化、そして最小限の RIL。ROM には意図的に入れていません。RIL は 201 メソッド中 27 しか実装しておらず、緊急発信はまだスタブです。人が持ち歩く電話に載せるものではありません。

その上で端末は何ができるか

6.12 カーネルでのハードウェア対応状況
Stateサブシステム備考
動作ディスプレイパネル、バックライト、スリープと復帰。カタログは 90 Hz ですが、実際にパネルを駆動しているのは 96 Hz です。コンポジタのフレーム予算を本当の周期 10.4 ms に合わせ直したところ、90 パーセンタイルのフレームが 150 ms から 25 ms になりました。
動作音声スピーカー、受話口、マイク、Bluetooth A2DP、通話音声 — すべてここで書いた HAL を通ります。スピーカーには 180 Hz のハイパスとチャンネル共有のリミッタを入れ、ピークでステレオ像がずれないようにしています。
動作携帯通信通話、SMS、モバイルデータを実回線で確認。モデムスタックは出荷時のものです。並行して作ったオープンなスタックは ROM には入れていません。
動作無線Wi-Fi、Bluetooth、NFC。Wi-Fi はカーネルモジュールの内側から立ち上げ、規制上のカントリーコードもそこで設定します。設定しないと接続まで至りません。
動作カメラ反転モジュールの論理カメラ 2 つとも — 静止画と動画。
動作指紋登録と照合。照合そのものはクローズドな trustlet の中で動いていて、これは今後も変わりません。
動作USBadb と MTP。以前はガジェットが認識されて 2 秒で消えていました。完全な出荷時イメージでも再現したので、この不具合は今回の作業で入ったものではなく工場出荷時からあったと確認できました。
動作電源工場出荷のバイナリから復元したドライバによる充電、CPU の両クラスタと GPU のサーマルゾーン、ケーブルを抜いた状態でのサスペンドと復帰。
未完成RPMBハードウェア鍵ストレージが MAC 検証に失敗します。ストレージは安全に縮退し、起動には影響しません。起動経路が工場で書き込まれた鍵とは別の鍵を導出している可能性が高く、そうであれば工場の鍵素材なしには直せません。
未対応もう一方のスロットA/B 両スロットの論理パーティション 6 つがすべて super 内の同じオフセットから始まるため、この端末に「空いているスロットに焼いて試す」は存在しません。ハードウェアの欠陥ではなく、インストールのやり方から来る結果で、先にそのスロットのメタデータを書き直せば解決します。
未対応仮想 SIMこの端末の売りである内蔵 vSIM。意図的に手をつけていません。

動作 未完成 未対応

どの行も実機で実際に使ったという意味で、ドライバがバインドしたとかデバイスノードが現れたという意味ではありません。かつてまさにその根拠で「動作」と記録したサブシステムが 3 つあり、3 つとも動いていませんでした。

動かしている端末

MindOne は MediaTek Helio G99 を積んだ市販の端末です。カードサイズ、サファイアの下に正方形の AMOLED、5000 万画素のレンズ 1 枚が反転して前面カメラにも背面カメラにもなります。ここに諸元を載せているのは、作業がこの条件に合わせる必要があったからで、端末を勧めるためのページではありません。出荷時は Android 12 世代のベンダーイメージ上の Linux 5.10 で、ブートローダーより上はすべて、下に挙げた 2 つのリポジトリで置き換わっています。

SoC
MediaTek MT6789 / MT8781V-CA · Helio G99、6 nm
CPU
Cortex-A76 2.2 GHz × 2 + Cortex-A55 2.0 GHz × 6
GPU
Mali-G57 MC2
メモリ
RAM 8 GB · ストレージ 256 GB(UFS)
ディスプレイ
4.02 インチ AMOLED、サファイアカバー、1080 × 1240
カメラ
Sony IMX766、5000 万画素、180° 反転モジュール — 背面と前面を兼ねる
本体
86 × 72 × 8.9 mm · 2,200 mAh
通信
LTE(5G なし)· NFC · 内蔵の仮想 SIM
出荷時
android12-5.10 ベンダーカーネル上の Linux 5.10.233 · Android 15
現在
このツリーの Linux 6.12.92 · LineageOS 23.2、Android 16

数字で見る

カーネル 6.12
6.12.92日常的に稼働中
290起動時に読み込まれるモジュール
339ソースからビルドするドライバツリー
172うち自前の修正が入っているもの
ここで書いたもの
10ベンダーに相当物がないカーネルモジュール
16 400デバイスツリーの実装行数
18バイナリから起こしたデバイスツリーのソース

検証したこと、していないこと

一人による独立した立ち上げです。粗いところがあるものと考え、おかしな挙動はたいてい既知だと思って構いません。工場出荷ファームウェアに戻す手段は必ず確保してください。

日常利用
あり — 自分の端末です。通話、データ通信、カメラ、音声、センサー、充電、サスペンド。
自前のシステムイメージ
あり。このツリーからビルドした super パーティション一式を端末に書き込み、そこから起動しています。
VTS / CTS
なし。どちらも実行していません。互換性の裏づけは存在せず、主張もしません。
認証
いかなる認証もありません。
再現ビルド
カーネルのみ、1 台のマシンで同じ出力先に対して確認。異なる絶対パスでのビルドは未検証です。

どう公開しているか

どちらのリポジトリもベンダーのバイナリを使わずソースからビルドでき、クリーンなクローンが生む ABI は端末で動いているものと同じです。カーネルのリポジトリは Android Common Kernel 自身と同じく、カーネルのバージョンごとにブランチを持ちます。android16-6.12 をビルドし、デバイスツリーをそれに対してビルドしてください。

01

Kernel · android16-6.12

Linux 6.12.92 · 現行

Google の Android Common Kernel、ブランチ android16-6.12-lts を手作業で移植し、デバイスサポートを載せたものです。復元したデバイスツリー、752 項目の defconfig、カーネル外のドライバツリー 339 本、そのうち 290 モジュールが実機で読み込まれます。出荷時のカーネルから 2 世代先で、現在の作業はすべてこのブランチに入ります。同じツリーと同じツールチェーンでの 2 回のビルドはバイト単位で同一の Image を出すので、端末で動いているものとクリーンなクローンから得られるものは同一物です。

02

Kernel · android14-6.1

Linux 6.1.175 · アーカイブ

元のベンダーカーネルからの最初の移植で、6.12 を可能にした一段です。デバイスツリーとドライバ作業の大半が実機で最初に確かめられたのはここでした。6.12 に置き換わるまでは日常用のカーネルとして動いていました。履歴として残していますが保守はしていません — 修正も、セキュリティのバックポートも、テストもありません。ドライバはここには重複して置かれておらず、6.12 ブランチにあって互換ヘッダ 1 枚でどちらのカーネルにも通ります。

03

Device tree · lineage-23.2

LineageOS 23.2 · Android 16 · 現行

LineageOS のデバイスツリーは普通は設定を運ぶものですが、ここには約 16,400 行の実装が入っています。クローズドなユーザー空間を、そのまま包み直すのではなく書き直しているからです。完全なプライマリ音声 HAL、カーネルの hf_manager に直結したセンサー HAL、VINTF のレベルが上がるなかでまだ書き直していないベンダー HAL を生かす HIDL→AIDL ブリッジ 4 本、そしてオープンなモデム用ユーザー空間。ここでビルドした super パーティション一式 — system、vendor、product、system_ext、両方の dlkm — がそのまま端末で起動します。

公開しないもの

この端末がなお必要とするプロプライエタリなユーザー空間 — 無線、GPU ドライバ、カメラライブラリ、そしてまだ書き直していない HAL — はどちらのリポジトリにもありませんし、今後も置きません。各自が自分の端末から取り出すものです。MediaTek と iKKO のバイナリも同様で、ブートローダー、セキュアファームウェア、コプロセッサのイメージ、モデムファームウェア、この個体のパーティションダンプは含みません。

使用技術

  • Linux 6.12
  • C
  • AArch64
  • MediaTek MT6789
  • Android GKI/KMI
  • Device Tree
  • Clang/LLVM
  • Ghidra
  • AOSP
  • LineageOS
  • Android HAL
  • Python

免責事項

このページに書かれていることは、明示・黙示を問わずいかなる保証もなく現状のまま提供されます。ブートローダーのアンロック、パーティションの書き換え、ここからリンクしているツールの実行は、端末上のすべてのデータを消し、端末を恒久的に起動不能にする可能性があります。実行はご自身の責任と判断で行ってください。ここに書かれたことに従った結果として生じた損失や損害について、端末に対するものかどうかを問わず、著者は一切の責任を負いません。

小売で購入した端末での個人的な研究プロジェクトであり、1 台の個体で起きたことの記録です。iKKO および MediaTek とは無関係で、両社の承認も支援も受けていません。