10年以上使ってきたmovaからイーモバイルのS12HTにメイン電話をかえました。 ひさしぶりにWindows機さわってます。 …だれかMSM7200のデータシートこっそり送ってくれませんか?(笑)

拡張端子

番号イヤホンビデオACPC(ホスト)ビット
Mic/V1MicVideo
Right2RR
ID3SW-AGNDAGND
ID4AGND
AGND5AGNDAGND
Left6LL
+5V1←1A←0.5A→8mA9800000c&0001
D-2↓15KD-
D+3↓15KD+
ID4GNDGND!9800000c&0002
GND5AGNDAGNDGNDGNDGND
miniAケーブルがつながれた(ホスト)かどうかは通例IDで判断するんですが、 ここを1A充電できるかどうかに使ってますね。 ってUSB miniAって規格からキャンセルになってますね。
(08-9-12)

Touch pro

s12htは0xa9800000がMSM_USB_PHYSで、ここにフルスピードなOTG USBが見えていますが、 Touch Proは0xa0800000がMEM_HSUSB_PHYSで、 ここにehci互換なOTG USBが見えています。 下のようにアクセスできますが、USBに電源供給されないとoem_init.dllがクロック有効(サブCPUコマンド)にしてくれません。
  mem= (BYTE*)VirtualAlloc(0, 4096, MEM_RESERVE, PAGE_READWRITE);
  VirtualCopy(mem, (void*)((DWORD)0xa0800000>>8), 4096
  , PAGE_READWRITE|PAGE_PHYSICAL|PAGE_NOCACHE);
  VirtualSetAttributes(mem, 4096, 0x80, 0x80, &cur);
a0800000: 0042fa05 000005c2 04020001 00000021
a0800010: 80070b08 00000808 00000000...
a0800100: 01000040 00010011 00000006 00000000
a0800110: 00000000 00000000 00000000 00000000
a0800120: 00000001 00000190 00000000 00000000
a0800130: 00000000 00003000 00000000 00000000 ...
電源供給さえなんとかなればehci.dllを微改造してねえ。 s12htも互換チップのマニュアルはあるんですが結構ohci/ehciと違ってるんで面倒。

ruu_signed.nbhファイル

xda-developersを見ればわかるんだけど、要約。 ruuはrom update utilityの略、 nbはnaked binary(べたデータ)の略。

nbh→nbg

nbgファイルを0x10000バイト毎に区切り、署名をつけて、さらに全体に署名をつけたのがnbhファイル。
//nbhファイル
  char マジック[7]= "R000FF\n";
  char 不明[16]= 0;
  struct ブロック {
    int ブロック長= 0x10000; //最後のブロックは<=0x10000
    int 署名長= 0x80; //リトルエンディアン
    byte フラグ= 1;
    byte nbgデータ[ブロック長];
    byte 署名[0x80];
  } ブロック1, ブロック2, ブロック3…
  struct ブロック {
    int ブロック長= 0;
    int 署名長= 0x80;
    byte フラグ= 2;
    byte データ[0];
    byte 署名[0x80]; //全体の署名
  } 署名ブロック;

nbg→個別ファイル

ファイル種類により最大32ファイルを含みます。
//nbgファイル
  int マジック[8]= (int)"HTCIMAGE";
  char デバイス名[0x20]= "NIKI100**"; //未使用部分は0
  int ファイル種類[32]= {0x301,0x200,…,0,0,0};
  int オフセット[32]= {0x200,0x1120200,…}; //nbg先頭からのオフセット
  int 長さ[32]= {0x1120000,0x40000,…};
  char CID[0x20]= "HTC__001";
  char バージョン[0x10]= "2.09.405.1";
  char 言語[0x10]= "USA";
  byte ファイル[32][長さ]; //最大32ファイル

ファイル種類

詳細はxda-developersを参照のこと。 nbhextract.exeによりnbhから個別ファイルへ展開されます。
コードサイズ内容展開ファイル名
0x100128KBIPL initial program loaderXX_IPL.nb
0x200256KBSPL secondary program loader01_SPL.nb
0x30117MBサブCPUコード00_Unknown.nb
0x400100MBメインCPUコード(CEOS)04_OS.nb
0x60x256KBスプラッシュ画面XX_XXXXSplash.nb

ブートシーケンス (以下推測含みます)

最近の機種にはNANDフラッシュが採用されていますが、これは直接コード実行はできず、一度RAM上に展開してから実行するようになっています。 また、NANDフラッシュは出荷時点で不良ブロックがあることがあり、代替ブロックテーブルを参照して別のブロックにアクセスする必要があります。
起動時、MSM7200中のマスクROMによりNANDの最初のブロック(2048バイトx64ページ=128KB)がRAM中に読み込まれ制御が移されます。なお、最初のブロックは不良ブロックでないことが保障されています。これがIPLにあたります。
次にIPLがSPLを代替ブロックテーブルを参照しながらRAMに読み込み、SPLに制御がうつります。SPLはサブCPU(Radio)コードやメインCPUコード(CEOS)をRAMに展開し、それぞれのCPUを起動します。
CEOSにはXIPという仕組みがあり、これはNOR型フラッシュやマスクROMを用いてDLLやEXEの直接コード実行を可能とし、RAMを節約するものです。このアドレスマップの中の共用DLL領域がそれにあたります。 NANDフラッシュの場合いずれにせよRAM上にロードしなければならないのでXIPの意味はあまりないのですが、依然としてサポートされており、XIP DLLはRAM上の解決済みのアドレスへロードされます。
CEからNANDフラッシュはドライバ経由でアクセス可能ですが、代替ブロックや不良ブロック新発生時や書き込みウェアレベリングなどいろいろ面倒な処理をやっているので、素のNANDデバイスがアクセス可能なわけではないです。

サブCPUコード (OO_Unknown.nb)

//サブCPUコード(diam)
  int マジック[2]= {0x8a914e07, 0xec55364b};
  int 時刻; //1970-1-1 00:00:00からの経過秒
  int 不明= 0x03f0;
  int 本体長= 0x13c0000;
  int 署名長= 0x0a00;
  int 不明= 0x59600000; //署名ID?
  int 不明= 0x5c260000;
  byte 本体[本体長]= {
    0000_0020:
    struct ブロック { //qcsbl
      int マジック[2]= {0x83838383, 0x73d71034};
      int 不明= 1;
      int ブロック長= 0xa9c;
      int 不明= 0x280;
      int アドレス= 0x8000e000;
      int サイズ= 0x101d4;
      int =サイズ;
      int アドレス末=アドレス+サイズ;
      int 不明= 0;
      int =アドレス末;
      int 不明= 0;
      byte qcsbl情報[ブロック長-0x30];
      byte 詰め[]= 0xff; //ブロックが128KB単位に満つるまで
    } qcsbl;

    0002_0020:
    struct ブロック {
      int マジック[2]= {0xaa01de33, 0xdbfe99af};
      int 不明= 1;
      int 不明= 0;
      byte ゼロ[0x800-16]= 0; //2KB単位に満つるまで
      byte 詰め[]= 0xff; //ブロックが128KB単位に満つるまで
    } 不明;

    0004_0020:
    struct mibibブロック {
      int マジック[2]= {0xfe569fac, 0xcd7f127a};
      int 不明= 3;
      int 不明= 2;
      byte ゼロ[0x800-16]= 0; //2KB単位に満つるまで
      struct dirページ {
        int マジック[2]= {0x55ee73aa, 0xe35ebddb};
        int タイプ= 3;
        int 総数= 0x10;
        struct {
          char 名前[16]; //"0:MIBIB" など
          int オフセット;
          int 長さ;
          int 不明= 0;
        } エントリ[総数];
        byte 詰め[]= 0xff; //ページが2KB単位に満つるまで
      } ディレクトリ情報;
      struct ページ {
        int マジック[2]= {0xfa0f129c, 0x5a8fb6c9};
        int タイプ= 1; //1はヘッダ情報
        char 名前[16]; //"0:OEMSBL1"等
        byte ゼロ[]= 0; //ページが2KB単位に満つるまで
      } oemsblページ0;
      struct oemsbl情報 {
        int 不明= 1;
        int 不明= 3;
        int 不明= 0;
        int アドレス=0x900000;
        int サイズ   =0x54724;
        int =サイズ;
        int =アドレス+サイズ;
        int 不明=0;
        int =アドレス+サイズ;
        int 0;
        byte 詰め[]= 0xff; //ページが2KB単位に満つるまで
      } oemsbl1;
      struct oemsbl情報 {
        int 不明= 2;
        int 不明= 3;
        int 不明= 0;
        int アドレス=0xa00000;
        int サイズ= 0x1133014;
        int =サイズ;
        int =アドレス+サイズ;
        int 不明=0;
        int =アドレス+サイズ;
        int 0;
        byte 詰め[]= 0xff; //ページが2KB単位に満つるまで
      } oemsbl2;
      byte obmsblページ3[0x800]= 0xff;
      byte obmsblページ4[0x800]= 0xff;
      byte obmsblページ5[0x800]= 0xff;
      byte obmsblページ6[0x800]= 0xff;
      struct ページ {
        int マジック[2]= {0xaa7d1b9a, 0x1f7d48bc};
        int タイプ= 3;
        int 総数= 0x10;
        struct {
          char 名前[16]; //"0:MIBIB" など
          int コード長; (利用されず?)
          int データ長; (利用されす?)
          int フラグ; //FFFFFFFF=通常、FFFFFFFE=mibib
        } エントリ[総数];
        byte 詰め[]= 0xff; //ページが2KB単位に満つるまで
      } ディレクトリ情報その2;
      struct ページ {
        int マジック[2]= {0x9d41bea1, 0xf1ded2ea};
        int タイプ= 1;
        int チェックサム?;
        byte 詰め[]= 0xff; //ページが2KB単位に満つるまで
      } チェックサム?;
      byte 詰め[]= 0xff; //ブロックが128KB単位に満つるまで
    } OEMSBL1情報;

    0006_0020:
    struct mibibブロック {
      int マジック[2]= {0xfe569fac, 0xcd7f127a};
      int 不明= 3;
      int 不明= 1; //ここが直前と異なる
      byte ゼロ[0x800-16]= 0; //2KB単位に満つるまで
      byte ディレクトリ情報[0x800]= 0xff;
      struct ページ oemsblページ0;
      struct oemsbl情報 oemsblページ1;
      struct elf情報 oemsblページ2;
      byte obmsblページ3[0x800]= 0xff;
      byte obmsblページ4[0x800]= 0xff;
      byte obmsblページ5[0x800]= 0xff;
      byte obmsblページ6[0x800]= 0xff;
      struct ディレクトリ情報その2; //前と全く同じ
      struct チェックサム;
      byte 詰め[]= 0xff; //ブロックが128KB単位に満つるまで
    } OEMSBL2情報;
    0008_0020〜: 詰め=0xff;

    0014_0020:
    struct ブロック {
      int マジック[2]= {0x5fe85ddf, 0x5264cebc};
      int 0, 0;
      char 名前[16]= "QCT_BOOT V522511";
      byte ゼロ[0x800-0x20]= 0; //2KB単位に満つるまで
      byte データ[]; //QCSBLデータ(プログラムコード)
           0014_0820〜 コード
           0014_f820〜 データ
           0015_09f4〜 FF詰め
      byte 詰め[]= 0xff; //ブロックが128KB単位に満つるまで
    } QCSBLデータ;
    0016_0020〜: 詰め=0xff;

    001c_0020:
    struct ブロック {
      int マジック[2]= {0xfa0f129c, 0x5a8fb6c9}; //既出マジック
      int タイプ=0; //0はデータが続く
      byte ゼロ[]= 0; //2KB単位に満つるまで
      byte データ[]; //ブロックが128KB単位に満つるまで
    } OEMSBL1-0;
    001e_0020: struct (同上) OEMSBL1-1;
    0020_0020: struct (同上) OEMSBL1-2; 埋めFFあり
    //総サイズはmibibブロック.oemsbl1.サイズ=0x54724;
    //このサイズはデータ本体、マジック用ページは含まない
    0022_0020〜: 詰め=0xff;

    0028_0020:
    struct ELFブロック {
      int マジック= 0x464c457f; //ELF
      byte ELFデータ[0x1133014-4];
      //サイズはmibibブロック.oemsbl2.サイズ=0x1133014;
      //このサイズはelfマジックを含む
      byte 詰め[]= 0xff; //ブロックが128KB単位に満つるまで
    } OEMSBL2;
  };
  013c_0020:
  byte 署名[署名長];
  byte 詰め[]= 乱数; //サブCPUコードが128KB単位に満つるまで
//dirエントリ(diam)
//ディレクトリ情報はQCSBL、OEMSBL1、OEMSBL2の開始ブロック位置のみ有効
           ディレクトリ情報  ディレクトリ情報その2      ロードアドレス
             開始    (長さ)  (コード) (データ) (フラグ)
0:MIBIB    00000000+0000000A 00000004:00000006:FFFFFFFE
0:QCSBL    0000000A+00000004 00000080:00000180:FFFFFFFF 8000e000+000101d4
        IPL。OEMSBL1を読み込み。
0:OEMSBL1  0000000E+00000006 00000180:00000180:FFFFFFFF 00900000+00054724
        SPL。フラッシュ書き換えやOEMSBL2の読み込み。
0:OEMSBL2  00000014+00000006 00000180:00000180:FFFFFFFF 00a00000+01133014/elf
        サブCPUコード本体。このelfはプログラムヘッダはあるけど
        セクションヘッダはないのでobjcopyではべたバイナリ化できない。
0:HTC      0000001A+00000010 00000400:00000400:FFFFFFFF
0:AMSS     0000002A+000000C0 00005680:00000980:FFFFFFFF
0:EFS2     000000EA+0000002C 00001100:00000500:FFFFFFFF
0:FOTA     00000116+00000008 00000200:00000200:FFFFFFFF
0:RESERVED 0000011E+00000002 00000080:00000080:FFFFFFFF
0:APPSBL   00000120+00000006 00000180:00000180:FFFFFFFF
0:MISC_MFG 00000126+00000002 00000080:00000080:FFFFFFFF
0:WLAN     00000128+00000002 00000080:00000080:FFFFFFFF
0:SPLASH1  0000012A+00000009 00000300:00000180:FFFFFFFF
0:SPLASH2  00000133+0000000E 00000500:00000200:FFFFFFFF
0:APPS     00000141+00000278 00013B80:00000080:FFFFFFFF
0:EXT_ROM  000003B9+00000047 00002300:00000080:FFFFFFFF
OEMSBL2.ELF //プログラムは仮想空間で実行される…ARM mapping
    LOAD off    0x00001000 vaddr 0x17ea9000 paddr 0x17ea9000 align 2**0
         filesz 0x0000017c memsz 0x00001000 flags --- 2200000
         設定データ

    LOAD off    0x00008000 vaddr 0xf0000000 paddr 0x00a00000 align 2**15
         filesz 0x0001bfe4 memsz 0x0001fdd8 flags rwx
         コード
    LOAD off    0x00028000 vaddr 0xf0020000 paddr 0x00a20000 align 2**15
         filesz 0x00006000 memsz 0x00006000 flags rw-
         "NICTOKL4" "Open Kernel Labs" コードもあり

    LOAD off    0x00030000 vaddr 0xb0000000 paddr 0x00a61000 align 2**15
         filesz 0x0000e3ff memsz 0x0000e3ff flags r-x
         コード "memsection" メモリ管理ライブラリ?
    LOAD off    0x00040000 vaddr 0xb0040000 paddr 0x00af0000 align 2**15
         filesz 0x00000178 memsz 0x00017000 flags rw-
         "0000000..."
    LOAD off    0x00041000 vaddr 0xb0d00000 paddr 0x00a38000 align 2**12
         filesz 0x00002000 memsz 0x00002000 flags rw-
         "ig_naming" "quartz_servers" "AMSS"
    LOAD off    0x00044000 vaddr 0xb0e00000 paddr 0x00a3a000 align 2**12
         filesz 0x00004000 memsz 0x00004000 flags rw-
         "ig_naming" "quartz_servers" "AMSS"

    LOAD off    0x00050000 vaddr 0xb0100000 paddr 0x00a26000 align 2**15
         filesz 0x00006f9f memsz 0x00006f9f flags r-x
         コード "naming.c" "asynch.c"
    LOAD off    0x00058000 vaddr 0xb0140000 paddr 0x00a2d000 align 2**15
         filesz 0x000000d8 memsz 0x000001b8 flags rw-
         データ

    LOAD off    0x00060000 vaddr 0xb0200000 paddr 0x00a2e000 align 2**15
         filesz 0x000089b3 memsz 0x000089b3 flags r-x
         コード "qdms_server"
    LOAD off    0x00070000 vaddr 0xb0240000 paddr 0x00a37000 align 2**15
         filesz 0x000000d8 memsz 0x0000028c flags rw-
         データ

    LOAD off    0x00071000 vaddr 0xb0300000 paddr 0x00a40000 align 2**2
         filesz 0x00008120 memsz 0x00020a9c flags rwx 80000000
         コード "QUARTZ_SERVERS" "KXMUTEX_FLASH_DRV_SHARED"

    LOAD off    0x0007a000 vaddr 0x00b07000 paddr 0x00b07000 align 2**12
         filesz 0x00003000 memsz 0x00003000 flags r-x 81000000
    LOAD off    0x0007e000 vaddr 0x00b0a000 paddr 0x00b0a000 align 2**12
         filesz 0x0086f000 memsz 0x0086f000 flags r-x 1200000
    LOAD off    0x008ee000 vaddr 0x01379000 paddr 0x01379000 align 2**9
         filesz 0x0001ffa4 memsz 0x00ab1100 flags rwx 1000000

    LOAD off    0x0090e000 vaddr 0x17300000 paddr 0x17300000 align 2**12
         filesz 0x007fa000 memsz 0x007fa000 flags r-x 1200000
         thumbコード
    LOAD off    0x01109000 vaddr 0x17afa000 paddr 0x17afa000 align 2**12
         filesz 0x00029dfc memsz 0x0035e000 flags rw- 1000000
         データ

    LOAD off    0x01133000 vaddr 0x17e58000 paddr 0x17e58000 align 2**3
         filesz 0x00000014 memsz 0x00050040 flags rw- 1600000

CEページへ戻る メモランダムに戻る