2012年4月11日水曜日

kernelをSDカードからブートする

なんだか、更新が久しぶり。4月は忙しい。
が、何もしてなかったわけじゃなく、kernelハックをごそごそやってた。

kernel sourceがリリースされて、有志のハックが本格的に始まっている。
xdaのフォーラムとかで徐々に成果が報告されているので、個人的にも色々いじってみている最中だ。

で、少し前に、ハックkernelを簡単に動かす方法として、SDカードからブートする方法が公開されていた。[DEV] Lenovo Ideapad A1 Kernel Development/Testing

しかし、このフォーラムの記事通り作業をしても上手くいかない場合がある。
実は私がハマった一人だ(笑)

bootableなSDカードを作るのは結構シビアで、ディスク領域のファイル配置やパーティションの切り方にも気を使う必要がある。
上記フォーラムでは、bootableなSDカードの生成に omap3-mkcard.sh というスクリプトを使用しているが、これで上手くいかない場合、手動でSDカードを作る必要がある。
その方法をメモしておく。

使用した環境は、VMware 上の Ubuntu 10.04 LTS(64bit)
最初に、gconf-editor を使って、Ubuntuのドライブオートマウントを切っておく。
オートマウントされると、SD内のファイル配置が壊されたりするので、念のため切っておくほうが良い。
方法は、「gconf-editor media_automount」でググれば分かるはず。

次に、上記フォーラムより必要なファイルをダウンロードしておく。
MLO
u-boot.bin
omap3-mkcard.sh    (今回は使用しない)
ramdisk-cm7.ub    (CM7環境の人はこれを使用)
ramdisk-row-2643.ub  (2643環境の人はこれを使用)
それとは別に、ブートさせるカーネルイメージ uImage を準備する。
これは通常、kernelソースからビルドしたものを用意すればいい。
今回はテスト用に2375_ROWのカーネルを使用してみる。
ファームのアーカイブから uImage を取り出しておく。

以下、面倒なのでrootにて作業している。

まず、bootableなSDカードを作る。

Ubuntu環境にSDカードを刺し、デバイス位置を確認する。
# dmesg
[ 1452.618571] sd 7:0:0:0: [sdb] Assuming drive cache: write through
[ 1452.618580]  sdb: sdb1
[ 1452.639529] sd 7:0:0:0: [sdb] Attached SCSI removable disk
仮に、/dev/sdb がSDカードとする。各自の環境に合わせて読みかえるべし。

で、パーティションを手動で切っていく。
既存のパーティションは削除してまっさらにする。
# fdisk /dev/sdb

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help): p

Disk /dev/sdb: 2041 MB, 2041577472 bytes
255 heads, 63 sectors/track, 248 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1         248     1992028    c  W95 FAT32 (LBA)

Command (m for help): d
Selected partition 1

Command (m for help): p

Disk /dev/sdb: 2041 MB, 2041577472 bytes
255 heads, 63 sectors/track, 248 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
次に、エキスパートモードを使用してディスクパラメータを設定する。
head = 255
sector = 63
シリンダはディスク容量(上記、赤文字)から計算する。
cylinder = ディスク容量 / head / sector / 512
         = 2041577472 / 255 / 63 / 512
         = 248.208
小数切捨 = 248
Command (m for help): x

Expert command (m for help): h
Number of heads (1-256, default 63): 255

Expert command (m for help): s
Number of sectors (1-63, default 62): 63
Warning: setting sector offset for DOS compatiblity

Expert command (m for help): c
Number of cylinders (1-1048576, default 1020): 248

Expert command (m for help): r
パーティションを切って、パーティションタイプを指定する。
第1パーティションは、FAT32、サイズ64M、Boot。
第2パーティションは、Linux、サイズ残り全部。
Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-248, default 1):
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-248, default 248): +64M

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (10-248, default 10):
Using default value 10
Last cylinder, +cylinders or +size{K,M,G} (10-248, default 248):
Using default value 248

Command (m for help): t
Partition number (1-4): 1
Hex code (type L to list codes): c
Changed system type of partition 1 to c (W95 FAT32 (LBA))

Command (m for help): t
Partition number (1-4): 2
Hex code (type L to list codes): 83

Command (m for help): a
Partition number (1-4): 1

Command (m for help): p

Disk /dev/sdb: 2041 MB, 2041577472 bytes
255 heads, 63 sectors/track, 248 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *           1           9       72261    c  W95 FAT32 (LBA)
/dev/sdb2              10         248     1919767+  83  Linux
以上でパーティションはOK。
テーブルの書き込み。
Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
各パーティションをフォーマットして使えるようにする。
第1パーティション。/dev/sdb1 VFAT、ラベル名 boot
# mkfs.vfat -c -F 32 -n "boot" /dev/sdb1
第2パーティション。/dev/sdb2 ext3、ラベル名 rootfs
# mke2fs -j -L "rootfs" /dev/sdb2
さてさて、これでSDカードがフォーマットされたので、ブートに必要なファイルをコピーして環境を作っていく。

まず、boot領域。
ここには、MLO, u-boot.bin, uImage を配置する。
mountポイントを /media/tmp/ としてmount。ダウンロードしておいたファイルをコピー。
コピーする順番があるらしく、MLOを一番にコピーする必要がある。
# mount /dev/sdb1 /media/tmp/
# cp ~/MLO /media/tmp/
# cp ~/u-boot.bin /media/tmp/
# cp ~/uImage /media/tmp/
# umount /media/tmp/
次に、rootfs領域。
ここにはブート時に使用する/ファイルシステムを置いておく。
ダウンロードしたramdiskイメージを解凍して展開する。
2643の環境を使用する場合の例。
# mount /dev/sdb2 /media/tmp/
# dd if=~/ramdisk-row-2643.ub of=/media/tmp/ramdisk.img.gz bs=64 skip=1
# cd /media/tmp
# gunzip ramdisk.img.gz
# cpio -idmv < ramdisk.img
/media/tmp/ 内に / 以下のファイルシステムが展開される。
最後に、
# cd
# umount /media/tmp/
して、おしまい。

A1の電源を切り、作成したSDカードを刺して電源ONすれば、SD側のカーネルをロードして起動してくるはず。
設定-タブレット情報からカーネルバージョンやビルド番号を確認しておく。

もし、SD側のカーネルを読まないで起動してたり、Lenovoロゴでループする場合はSDカードがおかしいので作り直し。
結構、シビアなのでブートさせるまでに苦労するかもしれない。

しかし、これができるとハックカーネルを手軽に試せるのでとても便利。
本体の環境を壊さずに、SDカードの差し替えだけで済むのは画期的。
デバッグにも使えるし。
自家製のカーネルを放り込んで試すのが楽になってうれしい限り。

2 件のコメント:

  1. 無事、SDカードを作成することができました。ありがとうございます。

    アップされていたcifs.koを利用するためのハックカーネルを無事起動でき、
    cifsマウントも行うことができました。

    テストもできたので、A1本体に焼いてしまいたいんですが、
    どうすればいいでしょうか?

    返信削除
  2. こんにちは。
    カーネルイメージを入れ替えるだけなら、ファームzip内のuImageを入れ替えて焼けばよいはずです。
    cifs.koをビルトインしたカーネルならこれで事足りるはずです。

    モジュールとしてロードしているなら、ロード処理をinit.rcなどに書く必要があると思うので、ramdisk-uboot.imgを解いて書き直し、リパックしなければならないでしょう。

    この辺りの作業は、どのように実現しているかによって手順が異なるので、詳細までは分かりません。
    cifs.koを拾ってきた関連のフォーラムなどにはヒントはありませんか?

    返信削除