Pylone

Pylone Blog

PowerPCボードADS512101へのLinuxカーネルの移植

Posted by Masashi YOKOTA

Freescale社製PowerPCボードADS512101へLinuxカーネルを移植する手順を紹介します。

Freescale社ではADS512101用のLinuxBSPを公開しており、ソースコードから環境を構築することが可能ですが、Linuxカーネルのバージョンが2.6.24と若干古いため、比較的新しいバージョンを移植することが目的です。

予め

  • PowerPC向けクロス開発ツール
  • tftpサーバ

をインストールした環境を前提とします。

尚、使用するU-Boot、及びLinuxカーネルのバージョンは以下のとおりです。

  • U-Boot 2009.1
  • Linuxカーネル 2.6.28

U-Bootのビルド

オフィシャルサイトからソースコードを取得し、展開します。

% wget ftp://ftp.denx.de/pub/u-boot/u-boot-2009.01.tar.bz2
% tar xjfv u-boot-2009.01.tar.bz2

ターゲットにADS5121を指定してビルドします。

% cd u-boot-2009.01
% make ads5121_config
% CROSS_COMPILE=powerpc-linux-gnu- make

Linuxカーネルのビルド

オフィシャルサイトからソースコードを取得し、展開します。

% wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.28.tar.bz2
% tar xjfv linux-2.6.28.tar.bz2

ADS5121ボード用(v2.6.28向け)のパイロン製パッチを取得・適用します

% wget http://code.pylone.jp/hg/linux-2.6-ads5121-mq/raw-file/tip/ads5121
% cd linux-2.6.28
% patch -p1 < ../ads5121

カーネル設定ファイルを設置後、必要に応じて設定を変更しビルドします(デフォルトでU-Boot形式が生成されます)。

% cp arch/powerpc/configs/ads5121_defconfig .config
% ARCH=powerpc CROSS_COMPILE=powerpc-linux-gnu- make menuconfig
% ARCH=powerpc CROSS_COMPILE=powerpc-linux-gnu- make

デバイスツリーのビルド

デバイスツリーとは簡単に説明すると、

  • PowerPC/Linux固有の仕組みで、ボード依存のデバイス情報(I/Oアドレス等)を定義したもの
  • デバイスツリーを定義したソースファイル(*.dts)をコンパイラ(dtc)にてコンパイルしバイナリファイル(*.dtb)を得る
  • *.dtbファイルはLinuxカーネルイメージとは別にメモリ上に置かれ、Linuxカーネルはその内容からボードに関する各デバイス情報を把握する

といったものです。

デバイスツリーコンパイラはLinuxカーネルに含まれているため、以下の様にしてADS5121向けデバイスツリーソースをコンパイルします。

% cd (Linuxカーネルのディレクトリ)/arch/powerpc/boot
% ./dtc -O dtb -o ads5121.dtb dts/mpc5121ads.dts

Flash更新

tftpに備えて、これまで生成したバイナリファイルを、tftpサーバのディレクトリ(/srv/tftp/とします)にコピーしておきます。

# cp (U-Bootのディレクトリ)/u-boot.bin /srv/tftp/
# cp (Linuxカーネルのディレクトリ)/arch/powerpc/boot/uImage /srv/tftp/
# cp (Linuxカーネルのディレクトリ)/arch/powerpc/boot/ads5121.dtb /srv/tftp/

シリアルコンソールとしてシリアルクロスケーブルをHostPCとボードを接続します。通信設定は以下のとおりです。

ボーレート
115200
ビット長
8
フロー制御
なし
ストップビット
1

ボードの電源を投入後、SW1を押下しボード標準のU-Bootを起動します。このとき、

Hit any key to stop autoboot:  

のカウントダウンが開始されたらキャンセルします。

tftpに備え、必要に応じて環境変数を設定します。 (ここでは、tftpサーバとなるHostPCのIPアドレスを192.168.0.26、ボードのIPアドレスを192.168.0.120とします)

=> setenv netmask=255.255.255.0
=> setenv ipaddr=192.168.0.120
=> setenv serverip=192.168.0.26

先ほどビルドしたU-BootをFlashに書き込みます。FlashのI/O開始アドレスは 0xFC000000 で、内容は以下の様になっています。

アドレスセクタ番号内容
FC0000000Protected
FC0400001File system
FFC40000241Linux カーネル
FFEC0000251Device tree
FFF00000252U-Boot
FFF40000253U-Boot 環境変数

まず、更新するU-BootをRAM上のダウンロード領域(0x20000000)へダウンロードします。

=> tftp 2000000 u-boot.bin
Using FEC ETHERNET device
TFTP from server 192.168.0.26; our IP address is 192.168.0.120
Filename 'u-boot.bin'.
Load address: 0x2000000
Loading: ################################################
done
Bytes transferred = 241680 (3b010 hex)

そして、Flashのライトプロテクトを解除、該当のセクタを消去し、書き込みます。

=> protect off bank 1
=> erase 1:252-252
=> cp.b 2000000 fff00000 3b010

上記cpコマンドのサイズ(0x3b010)はtftpコマンドで実際に転送されたサイズを指定しています

Linuxカーネルを更新する場合も同様の手順になります。

=> tftp 2000000 uImage
=> protect off bank 1
=> erase 1:241-250
=> cp.b 2000000 FFC40000 <size>

FlashのライトプロテクトはU-Boot更新時に解除していますので続けて更新する場合は不要です。

デバイスファイルも同様の手順です。

=> tftp 2000000 mpc5121ads.dtb
=> protect off bank 1
=> erase 1:251-251
=> cp.b 2000000 FFEC0000 <size>

起動

ボード標準のU-Boot起動コマンドでFlash上のrootfsから起動するには以下の様にします。

=> run jffs2boot

カーネルコマンドラインを指定して起動する場合は以下の様にします

=> set bootargs console=ttyPSC0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2 mem=256M
=> bootm ffc40000 - ffec0000

bootmコマンドの引数はそれぞれ、

  • ffc40000 : カーネルのアドレス
  • - : initial ramdiskのアドレス(未使用なので省略を示す'-')
  • ffec0000 : デバイスツリーのアドレス

と言う意味になります。

Flashを更新せずにRAMから起動する場合

デバッグ段階などで、Linuxカーネルやデバイスツリーを頻繁に更新するようなケースで、毎回Flashに書き込みをしていては非効率です。そこで両ファイルをFlashに書き込まずにRAMから起動する場合は以下の様にします。

=> tftp 2000000 uImage
=> tftp 3000000 ads5121.dtb
=> set bootargs console=ttyPSC0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2 mem=256M
=> bootm 2000000 - 3000000

または、Flash上のデバイスツリーファイルを使用する場合は、最後のbootmコマンドのデバイスツリーファイルのアドレスを、

=> bootm 2000000 - ffec0000

とします。

jffs2イメージをloopback mount

Posted by Seiichi SATO

block2mtdドライバを使えば、jffs2イメージファイルをloopbackでmountできます。

erasesize 128K (131072) のrootfs.jffs2を/mntにmountする場合

mount:

# modprobe jffs2
# modprobe mtdblock
# losetup /dev/loop0 rootfs.jffs2
# modprobe block2mtd block2mtd=/dev/loop0,131072
# mount -t jffs2 -o ro /dev/mtdblock0 /mnt

umount:

# umount /mnt
# rmmod block2mtd
# losetup -d /dev/loop0

seq_fileの使い方

Posted by MINAMI Hirokazu

Linuxカーネルが持つ、疑似ファイルの実装を補助する機構を紹介します。

カーネルからユーザ空間へデータを渡す手段としては、/proc や /sys 以下に作成した疑似ファイルを使うことが多いでしょう。

渡したい値が単純な型の場合はカーネル組込みのヘルパ関数を使えば十分(sysfs 経由でモジュールパラメータにアクセスsysfs 経由でモジュールパラメータにアクセス (2))ですが、 より複雑なデータを渡すならば:

  • 疑似ファイルの内容となるテキスト量が大きい場合、カーネル空間に全体を保持たくない。
  • データ構造を操作に時間がかかる場合、ユーザ空間から要求された部分だけを処理することが望ましい。
  • 同時に複数の読み手が存在したり、読み出し途中でデータが変更される場合の排他が必要。

などの点を考慮するべきです。

本記事では、シーケンシャルな疑似ファイルを実装するために用意されている補助関数群について解説します。カーネル内でも広く使われている機構なので、知っておくとコードを読む際にも役立つでしょう。

seq_file

VFSの層ではファイル中の位置はバイト単位で扱われます。固定長のバッファで扱える程度のデータ量ならよいのですが、疑似ファイル内容を一括生成・保持できない場合、自力で出力済のバイト数管理やバイト単位でのシークを実装するのは手間がかかります。

fs/seq_file.cには出力したいデータが

  • 通し番号が付けられる(配列や木などの)要素の集合として表現できる
  • 要素の番号がわかれば、その要素の文字列表現が得られる

という条件を満たすとき、各要素へのアクセスをイテレータ操作として抽象化する仕組みが用意されています。

これを使うと、所定のアクセサを作成するだけで、VFSに登録する struct file_operations のメンバのほとんどをカーネルから提供される汎用関数でまかなうことができます。

使用例

サンプルとして、全ttyについてdebugfs上の疑似ファイル経由として termios状態を一覧するカーネルモジュールのソースtermios_dumper.cを用意しました。

個別のttyの状態取得ならtcgetattr()でも十分なのですが、システム上で現在activeな全てのttyをリストするために、カーネル内部のデータ構造を直接読んでいます。

疑似ファイルの登録

seq_fileを使用する場合でも、ファイルシステムへの疑似ファイルの登録は通常のまま

  1. struct file_operationsを作成
  2. ファイルシステム毎の登録関数の呼び出し

という手順で行います。

ただし、VFSに渡すstruct file_operationsのうち、読みこみ可能な疑似ファイルを実装するために必要な

  • open
  • read
  • llseek
  • release

のうちread, llseek, releaseとしては、seq_fileで実装されているseq_read, seq_lseek, seq_releaseをそのまま使用できます。

.openに登録する関数では、

  • open()されたファイルに対して、seq_open()を呼んでハンドラを登録。
  • 必要ならリソースの確保/ロック

を行ないます。

サンプルでは登録先のファイルシステムをdebugfsとしたので、以下のようにしています。

static const struct file_operations fops = {
.open = termios_dumper_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
...
static int __init termios_dumper_init(void)
{
...
if(IS_ERR(fs_root = debugfs_create_dir(KBUILD_BASENAME, NULL)))
return PTR_ERR(fs_root);
if(IS_ERR(fs_file = debugfs_create_file("state", 0444, fs_root, NULL,
&fops)))
return PTR_ERR(fs_file);

この例では、特にリソースの初期化が必要ないため、.openに登録したtest_seqfile_openの実装はseq_open()の呼び出しだけです。

static int test_seqfile_open(struct inode *inode, struct file *file)
{
return seq_open(file, &seqfile_ops);
}

seq_operations

読み出し用のイテレータに必要な操作:

  • 初期化
  • 終了処理
  • 「次」の要素に移動
  • 値(文字列表現)の取得

は、

struct seq_operations {
void * (*start) (struct seq_file *m, loff_t *pos);
void (*stop) (struct seq_file *m, void *v);
void * (*next) (struct seq_file *m, void *v, loff_t *pos);
int (*show) (struct seq_file *m, void *v);
};

の各メンバとして登録されます。

start

seq_file用のファイルがopen()された時に呼ばれます。

  • 使用するリソースの確保
  • イテレータの初期化

を行ない、成功した場合には初期化済みのイテレータ、失敗した場合はNULLを返すことになるでしょう。

引数*posが0より大きい場合には、その位置を指すようにしたイテレータが返却されるべきです。

※ イテレータの更新処理は、(pos)ではなく、(*pos)を使います。

イテレータを進める処理は、next()からの処理でも必要となるため、共通化してもよいでしょう。サンプルでは update_iterator()としています。

next

seq_fileが、現在のイテレータからのデータを消費し終えた時、現在のイテレータと次に指すべき位置を引数として呼ばれます。

読み手のread()に対応していると考えてよいでしょう。ただし、カーネルによる先読み処理の対象となるため、read()の度にかならず呼ばれるわけではありあせん。また、読み手が小量のデータしが要求していなくても、さらに先まで要求されることがあります。

指定位置を指すイテレータを用意して、それへのポインタを返します。この場合返却したポインタは後述するshow()への引数として使われます。

処理に失敗した場合はNULLを返却します。このとき、続いてstop()が呼ばれますが、stop()の引数にはNULLしか渡らないため、リソースの開放にイテレータが必要なら、next()内で済ませておく必要があります。

stop

読み手に十分なテキストが渡ったか、next()からデータがもうないことを通知した(NULLを返した)後に呼びだされます。

リソースの開放を行なうべきですが、引数として渡されるポインタはNULLの場合があることに注意が必要です。

show

引数として渡されたイテレータから、読み手に渡す(疑似ファイルの内容となる)文字列を構築します。

構築にはseq_printf(), seq_puts()などのヘルパ関数を使用します。これらのヘルパは繰替えし呼ぶこともでき(追記されます)、最終的な長さは自動的に管理されるので、成功時には0を返せば適切に処理されます。

ただし、一度に構築できる文字列の全長はPAGE_SIZE程度なので、長くなりすぎる場合はイテレータの構造を変える必要があるでしょう。

サンプルコードでは、現在のイテレータが指しているtermiosの情報を、seq_printf()経由でgrepしやすい書式に変換しています。

サンプルtermios_dumper.cについての補足

サンプルとして使用したコードtermios_dumper.cでは、カーネルから公開されていはいttyドライバのリストの先頭要素のアドレスを知るために、struct tty_driverのmagic要素を用いて検索していますが、これは低い確率ですが(メモリ中の値が偶然TTY_MAGICと一致したり、get_current_tty()が呼べない場合に)失敗する可能性のある処理です。確実を期すなら、カーネルの公開シンボルにtty coreのtty_driversを追加するか、専用のアクセサを追加するべきでしょう。

また、ttyサブシステム内の構造体を辿る処理はttyのmutexを取得した上で行うべきなのですが、

  • tty_mutexを占有すると副作用が大きい(ロック中に新規にttyを開こうとした他のプロセス全てが停止するため)
  • 改造して失敗したときにシステムをロックしてしまう
  • 今回のサンプルでは読み出ししかおこなわないため、整合性が崩れても大きな問題にならない

ため、デモ目的では不要と判断してコメントアウトしてあります。このため、疑似ファイルからの読出し途中でttyが増減すると、表示の一貫性が崩れることがあるでしょう。同様の理由で、kobjectの参照数カウントについても省略しています。

Bishopバージョンアップのお知らせ

Posted by Seiichi SATO

組込みLinux開発用CPUボードBishopに同梱されるソフトウェアのバージョンアップを実施いたします。

旧バージョン新バージョン
U-Boot1.2.0-pylone5 (変更なし)
Linuxカーネル2.6.22.1-pylone02.6.26.8-pylone0
ルートファイルシステムDebian GNU/Linux etch 4.0r3Debian GNU/Linux etch 4.0r5

2009年1月以降にご注文いただいた分から新バージョンにて出荷いたします。

既にご購入いただいたお客様へ

2008年12月までにご購入いただいたお客様につきましては、別途バージョンアップ手順をご案内いたします。

関連リンク

Bishopエミュレータ正式版リリース

Posted by Seiichi SATO

組込みLinux開発用CPUボードBishopエミュレータの正式版をリリースしました。

スクリーンショット (3124050495_0f2b581105.jpg)

ドキュメント

ダウンロード

Bishopエミュレータ
qemu-bishop-0.9.1-pylone1.tar.bz2
ソースコード
0.9.1-pylone1ダウンロード2.3MB
qemu-bishop-0.9.1-pylone1-setup.exe
win32 installer
0.9.1-pylone1ダウンロード1.7MB
qemu-bishop_0.9.1-pylone1-1_i386.deb
deb
0.9.1-pylone1-1ダウンロード461.0KB
qemu-bishop-0.9.1_pylone1-1.i386.rpm
rpm
0.9.1-pylone1-1ダウンロード462.8KB

関連記事

Bishop向けLinuxカーネルのテスト版 - 2.6.26.8

Posted by Seiichi SATO

正式版を公開しました - 記事: Bishopバージョンアップのお知らせ

Bishop 向け Linux カーネルのテスト版 (2.6.26.8) を公開します。

Linux-2.6.26.8-pylone0
linux-2.6.26.8-pylone0.tar.gz
ソースコード
2.6.26.8-pylone0ダウンロード61.4MB
uImage
バイナリ
2.6.26.8-pylone0ダウンロード1.7MB

sysfs 経由でモジュールパラメータにアクセス (2)

Posted by Seiichi SATO

以前の記事で sysfs からモジュールパラメータにアクセスする簡単な方法を紹介しましたが、今回はパラメータの型を独自に定義する例として Base36 のパラメータを持つ簡単なモジュールを紹介します。

コード

base36param.c:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
static int stored_value = 0;
static int param_set_base36(const char *val, struct kernel_param *kp)
{
if (('0' <= val[0]) && (val[0] <= '9')) {
stored_value = val[0] -'0';
return 0;
}
if (('a' <= val[0]) && (val[0] <= 'z')) {
stored_value = val[0] -'a' +10;
return 0;
}
if (('A' <= val[0]) && (val[0] <= 'Z')) {
stored_value = val[0] -'A' +10;
return 0;
}
return -EINVAL;
}
static int param_get_base36(char *buffer, struct kernel_param *kp)
{
if (stored_value < 0 || 36 < stored_value)
return -EINVAL;
if (stored_value < 10)
buffer[0] = '0' + stored_value;
else
buffer[0] = 'A' + stored_value - 10;
buffer[1] = '\0';
return 2;
}
/* dummy checker */
#define param_check_base36(name, p) __param_check(name, p, void);
static int __init base36param_init(void)
{
printk(KERN_INFO "%s called\n", __func__);
return 0; /* succeeded */
}
static void __exit base36param_cleanup(void)
{
printk(KERN_INFO "%s called\n", __func__);
return;
}
module_init(base36param_init);
module_exit(base36param_cleanup);
module_param(stored_value, base36, 0644);
MODULE_PARM_DESC(stored_value, "can write [0-9A-Za-z], read as [0-9A-Z].");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("MINAMI Hirokazu");
MODULE_DESCRIPTION("sample module which has a custom typed parameter");

Makefile:

KERNEL_SRC = /lib/modules/$(shell uname -r)/build
#CROSS_COMPILE =
#ARCH =
BUILD_DIR := $(shell pwd)
VERBOSE = 0

obj-m := base36param.o

all:
	make -C $(KERNEL_SRC) SUBDIRS=$(BUILD_DIR) KBUILD_VERBOSE=$(VERBOSE) modules

clean:
	rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *~ Module.symvers

ビルド

環境に応じて Makefile の KERNEL_SRC, CROSS_COMPILE, ARCH を修正し、make を実行します。

使い方

値 (Base36) をパラメータに書き込む:

# echo 'h' > /sys/module/base36param/parameters/stored_value

パラメータを読み込む:

# cat /sys/module/base36param/parameters/stored_value
H

解説

モジュールパラメータに独自の型を持たせるためには、module_param を使います。

module_param(stored_value, base36, 0644);

module_param は以下のようなマクロです。

/* Helper functions: type is byte, short, ushort, int, uint, long,
   ulong, charp, bool or invbool, or XXX if you define param_get_XXX,
   param_set_XXX and param_check_XXX. */
#define module_param_named(name, value, type, perm)			   \
	param_check_##type(name, &(value));				   \
	module_param_call(name, param_set_##type, param_get_##type, &value, perm); \
	__MODULE_PARM_TYPE(name, #type)

#define module_param(name, type, perm)				\
	module_param_named(name, name, type, perm)

param_set_##type と param_get_##type が肝です。sysfs 経由でパラメータが読み書きされると、ここで登録されるparam_set_##type と param_get_##type が呼ばれます。(module_param_call の説明は省きます)

base36param.c の場合、プリプロセッサによってマクロ展開されたparam_set_base36 と param_get_base36 が登録されることになります。

マクロのコメントにある通り、 独自の型ではなく int などの場合はあらかじめ用意されているヘルパー関数群が使われるので自前で用意する必要はありません。

先日公開した 仮想バッテリドライバ はこれの応用です。 ファイルとして読み書きできるので ユーザ空間のプログラムとヘッダを共有する必要がない点は ioctl(2) より使い勝手がよいかもしれません。

関連記事

Virtual Battery Driver

Posted by Masashi YOKOTA

Linux kernel の機能の一部である Power supply class を利用した、仮想バッテリドライバを公開します。

概要

Power supply class は、sysfs 、及び uevent によってユーザースペースから電源状態に関するイベントの監視を可能にする仕組みですが、本ドライバはその仕組みを利用して、コマンドラインからAC電源、バッテリに関するイベントを生成し、電源状態の変化を仮想的に再現するためのものです。

パイロンでは、バッテリを持たないカスタムボードへ Android を移植する際に使用しています。

前提

本ドライバを使用するには、Linux kernel 2.6.25 以降を、

  • CONFIG_POWER_SUPPLY

を有効にしてコンパイルした環境が必要です。

また、Android で Power supply class から uevent を受けとるには、

  • CONFIG_SYSFS_DEPRECATED_V2

も有効にする必要があります。

導入手順

  1. アーカイブを展開して、Makefile 中の各変数である、
    • 組み込むカーネルのソースへのパス(本Makefileでは'KERNEL_SRC'としています)
    • ARCH
    • CROSS_COMPILE
    の内容を利用する環境に合わせて修正し、
    # make
    します。(または、各変数をコマンドラインから直接、定義します)
  2. 生成したモジュールを、対象のカーネルに組み込みます。
    # insmod virtual_battery.ko

    予め他のPower supply classドライバがロードされている状態で本ドライバを登録すると、Kernel Panic が起きてしまう点にご注意ください。

以上の手順を実行すると、sysfs のプラットフォームデバイスディレクトリ(/sys/devices/platform/) に、「virtual_battery.0」というディレクトリが生成されいるはずです。

$ ls /sys/devices/platform/virtual_battery.0/
bus                   power_supply:ac       uevent
modalias              power_supply:battery
power                 subsystem

また、sysfs のモジュールパラメータのディレクトリにも以下のようなディレクトリパスと仮想ファイル群が生成されているはずです。

$ ls /sys/module/virtual_battery/parameters/
ac_status           battery_health      battery_status
battery_capacity    battery_present     battery_technology

使用方法

電源状態を変更するには、sysfs に生成されたモジュールパラメータを使用します。

各仮想ファイルの使用方法は以下の通りです。

パラメータ初期状態説明
ac_statuson
off
onAC 接続の状態を変更します。
battery_statuscharging
discharging
not-charging
full
chargingバッテリの状態を変更します。
battery_healthgood
overheat
dead
overvoltage
failure
goodバッテリの劣化状態を変更します。
battery_presenttrue
false
trueバッテリの装着状態を変更します。
battery_technologyNiMH
LION
LIPO
LiFe
NiCd
LiMn
LIONバッテリの種類を変更します。
battery_capacity0から10050バッテリの残容量を変更します。
使用例

まずは現在の各値を確認してみます。sysfs の class ディレクトリ以下に、power_supply ディレクトリがあるので、そこの uevent を利用すると一覧を取得することができます。

# cat  /sys/class/power_supply/uevent
PHYSDEVPATH=/devices/platform/virtual_battery.0
PHYSDEVBUS=platform
POWER_SUPPLY_NAME=battery
POWER_SUPPLY_TYPE=Battery
POWER_SUPPLY_STATUS=Charging
POWER_SUPPLY_HEALTH=Good
POWER_SUPPLY_PRESENT=1
POWER_SUPPLY_TECHNOLOGY=Li-ion
POWER_SUPPLY_CAPACITY=50

バッテリ容量とバッテリ状態を変更してみます。

# echo 30 > /sys/module/virtual_battery/parameters/battery_capacity
# echo discharging > /sys/module/virtual_battery/parameters/battery_status

変更されているか確認してみます。

# cat /sys/module/virtual_battery/parameters/battery_capacity
30
# cat /sys/module/virtual_battery/parameters/battery_status
discharging

変更したタイミングで uevent が発生するので、バッテリの状況を動的に把握することが可能です。

組み込み用途向けのカスタムボードでは、バッテリを搭載していない事も多いと思いますが、そのような環境においても、本ドライバを利用することによって、ユーザスペースにおける電源管理の評価を行えるのではないでしょうか。

usbmon

Posted by MINAMI Hirokazu

Linux kernel 組込みの USB サブシステムをモニタする仕組み(usbmon)について紹介します。debugfs の活用例としても参考になるのではないでしょうか。

前提

Linux kernel 2.6.21以降を

  • CONFIG_USBMON
  • CONFIG_DEBUGFS

を有効にしてコンパイルした環境が必要です。

準備

  1. debugfsがまだマウントされていなければマウントします。 一般的に /sys/kernel/debug/ にマウントされるため、
    # mount -t debugfs none /sys/kernel/debug
    すればよいでしょう。
  2. usbmon をモジュールとして作成していた場合、カーネルに組み込みます。
    # modprobe usbmon

以上の手順を実行すると、debugfs の下(/sys/kernel/debug/usbmon/) に、「番号 + "s"/"t"/"u"」 という仮想ファイル群が生成されているはずです。

$ ls /sys/kernel/debug/usbmon/
0s  0u  1t  2s  2u  3t  4s  4u  5t  6s  6u
0t  1s  1u  2t  3s  3u  4t  5s  5u  6t

実際に何個のファイルが見えるかは、システム構成によります。

キャプチャ

「USBバス番号 + 'u'」という名前のファイルに、USBの通信内容が配送されます。

とりあえずバス番号に 0 を指定して("0u"を使って)、全通信を監視してみるとよいでしょう。

# cat  /sys/kernel/debug/usbmon/0u
dfaac8c0 2557329542 S Bo:5:004:2 -115 31 = 55534243 214b0100 00000000 00000600 00000000 00000000 00000000 000000
dfaac8c0 2557329639 C Bo:5:004:2 0 31 >
dfaac8c0 2557329649 S Bi:5:004:2 -115 13 <
dfaac8c0 2557331148 C Bi:5:004:2 0 13 = 55534253 214b0100 00000000 01
dfaac8c0 2557331171 S Bo:5:004:2 -115 31 = 55534243 224b0100 12000000 80000603 00000012 00000000 00000000 000000
dfaac8c0 2557331388 C Bo:5:004:2 0 31 >

行の内容は以下のようになっています。

  • URB Tag
  • timestamp
  • Event Type (S - submission, C - callback, E - error)
  • 通信種類([CZIB][io]): バス番号 : Device address : Endpoint number
  • URB Status word
  • データ長さ
  • データ内容

特定のデバイスだけを監視したい場合、lsusb の結果を参考にするとよいでしょう。たとえば

$ lsusb |grep PL2303
Bus 005 Device 005: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port

のようになっていた場合、 PL2303(USB-シリアルコンバータ)が5番に接続されているので、5uを使えばよいことがわかります。

その他の情報

疑似ファイルには他に 't'/'s'でおわるものがあります。

't'でおわるもの

'*t' は互換性のために残されている古い書式の疑似ファイルなので、通常使用する必要はないでしょう。

's'でおわるもの

'*s' からは usbmon 自体の動作状況を読むことができます。たとえば

# cat /sys/kernel/debug/usbmon/5s
nreaders 1 events 350 text_lost 0

なら、

  • 現在 1つのプロセスが バス#5 を監視して中
  • いままでに 350 個のURBが読み出された
  • 読まれる前にバッファから溢れてしまった URB はない

ことがわかります。

's' で終わるファイル群の処理では排他制御が考慮されないため、このインターフェース経由に高負荷をかける場合は何をしているのかよく理解した上で行なってください。

distcc による Linux カーネルのクロスコンパイル

Posted by Seiichi SATO

Bishop のカーネルを distcc による分散クロスコンパイル環境 でクロスコンパイルしてみました。

distcc の FAQ によると

You should use about twice the total number of CPUs available, but it dependson your network, program being compiled, available memory, etc. Experimentwith different values.

とのことなので、 とりあえず -j をプロセッサ・コア数の2倍にします。

まずは localhost 1台で計ってみます。(Xeon 2.40GHz x2, コア x4)

$ time make -j8 ARCH=arm CROSS_COMPILE=arm-linux-gnu- uImage
real    4m0.051s
user    13m14.462s
sys     1m12.329s

ホストを一台追加します。(host2: Pentium D 3.0GHz, コア x2)

$ export DISTCC_HOSTS="localhost host2"
$ time make -j12 ARCH=arm CROSS_COMPILE=arm-linux-gnu- CC="distcc arm-linux-gnu-gcc-4.1" uImage
real    2m4.114s
user    4m38.933s
sys     0m57.964s

もう一台追加します。(host3: Core 2 Duo E6600 2.4GHz, コア x2)

$ export DISTCC_HOSTS="localhost host2 host3"
$ time make -j16 ARCH=arm CROSS_COMPILE=arm-linux-gnu- CC="distcc arm-linux-gnu-gcc-4.1" uImage
real    1m32.039s
user    3m41.718s
sys     1m0.260s

さらにもう一台追加します。(host4: Celeron M 520 1.60GHz, コア x1)

$ export DISTCC_HOSTS="localhost host2 host3 host4"
$ time make -j18 ARCH=arm CROSS_COMPILE=arm-linux-gnu- CC="distcc arm-linux-gnu-gcc-4.1" uImage
real    1m22.078s
user    3m17.572s
sys     1m2.056s

グラフ

グラフ

リンク

busybox-staticによるinitramfs

Posted by Seiichi SATO

カスタムボードへのLinuxカーネル移植の初期段階でとりあえずのrootfsが必要になる場合は多いと思います。とりあえずのものにそれほど手間はかけたくないですが、カーネルのデバッグや動作確認のために機能はそれなりに欲しいところです。

方法は色々あると思いますが、パイロンではDebianの busybox-staticパッケージinitramfsを使うことが多いです。 手順は以下の通りです。

(例としてrootfsのディレクトリを/PATH/TO/ROOTFS/とします)

  1. busybox-staticパッケージをdpkg -xでばらしてbin/busyboxを/PATH/TO/ROOTFS/bin/busyboxにコピー
  2. /PATH/TO/ROOTFS/bin/busyboxへのシンボリックリンクPATH/TO/ROOTFS/initを追加
  3. mkdir /PATH/TO/ROOTFS/{dev,etc,proc}
  4. mknod /PATH/TO/ROOTFS/dev/console c 5 1

busyboxのinitは/etc/init.d/rcSを読み込むので起動直後の処理はrcSに加えます。最低でも/procのマウントさえしておけばよいでしょう。

/PATH/TO/ROOTFS/etc/init.d/rcS:

#!/bin/sh
mount -t proc proc proc

カーネルにinitramfsとして組み込むにはCONFIG_BLK_DEV_INITRDとCONFIG_INITRAMFS_SOURCEを指定します。

CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=/PATH/TO/ROOTFS/

debootstrapの前半部分をホストで、後半をターゲットで行う手順

Posted by Seiichi SATO

何もインストールされていないターゲット向けにDebian基本システムを作る手順です。Debianの作法的に正しいかどうかはわかりません。

ホスト側で前半部分を実行

NFS-Rootのホスト側ディレクトリを/nfsroot/etch-ARCH として説明します。

ARCHはアーキテクチャ(arm, mipsel, powerpcなど)に置き換えてください。

debootstrapを--foreignオプションで実行します。

# debootstrap --foreign --arch ARCH etch /nfsroot/etch-ARCH http://ftp.debian.org/debian/

NFS-Root用の/etc/fstabを用意します。

# echo "proc /proc proc defaults 0 0" > /nfsroot/etch-ARCH/etc/fstab
# echo "ホストのIPアドレス:/nfsroot/etch-ARCH / nfs defaults 0 1" >> /nfsroot/etch-ARCH/etc/fstab

/dev/consoleを作ります。

# mknod /nfsroot/etch-ARCH/dev/console c 5 1

NFS-Rootでターゲットを起動

NFSサーバの設定については触れません。

カーネルパラメータでホストの/nfsroot/etch-ARCHをNFS-Rootとして指定してカーネルを起動します。

カーネルパラメータの例:

console=ttyS0,115200n8 root=/dev/nfs nfsroot=ホストのIPアドレス:/nfsroot/etch-ARCH/ ip=ホストのIPアドレス:::サブネットマスク::eth0: init=/bin/sh

ターゲットで後半部分を実行

debootstrapを実行するための準備をします。
# mount -n -o remount,rw /
# mount -n /proc
# export PATH=/bin:/sbin:/usr/bin:/usr/sbin
# date -s "2008-2-27 18:33"
debootstrapを--second-stageオプションで実行します。
# /debootstrap/debootstrap --second-stage --no-resolve-deps

ターゲット向けの設定について

上記手順で作成したDebian基本システムをターゲットのNANDやCFなどにインストールして使う場合、事前にターゲットの環境に合わせて設定が必要になります。

よくある設定としては

  • /etc/inittab
  • /etc/fstab
  • /etc/securetty
  • /etc/resolv.conf
  • /etc/network/interfaces

といったところでしょうか。

シリアルコンソールであればttySnも作っておくといいかもしれません。

# cd /nfsroot/etch-ARCH/dev
# ./MAKEDEV ttyS

リンク

dpkg-crossの--exclude オプション

Posted by Seiichi SATO

dpkg-crossの基本的な使い方を知っている方向けの記事です。

dpkg-crossの--excludeオプションはクロスへ変換する際にDependsから特定のパッケージを取り除くオプションです。 最近追加 されたらしいのですが、使ってみたら便利だったので紹介します。

こんな感じです。

普通にクロスパッケージ化すると

$ dpkg -f lib64gcc1_4.1.1-21_powerpc.deb | grep Depends
Depends: gcc-4.1-base (= 4.1.1-21), libc6-ppc64 (>= 2.3.6-7)
$ dpkg-cross -a powerpc -b lib64gcc1_4.1.1-21_powerpc.deb
Building lib64gcc1-powerpc-cross_4.1.1-21_all.deb
$ dpkg -f lib64gcc1-powerpc-cross_4.1.1-21_all.deb | grep Depends
Depends: gcc-4.1-base (= 4.1.1-21), libc6-ppc64-powerpc-cross (>= 2.3.6-7), libc6-ppc64-powerpc-dcv1

となります。

--excludeを使ってgcc-4.1-baseへの依存を削ると

$ dpkg-cross -a powerpc -b --exclude gcc-4.1-base lib64gcc1_4.1.1-21_powerpc.deb
Building lib64gcc1-powerpc-cross_4.1.1-21_all.deb
$ dpkg -f lib64gcc1-powerpc-cross_4.1.1-21_all.deb | grep Depends
Depends: libc6-ppc64-powerpc-cross (>= 2.3.6-7), libc6-ppc64-powerpc-dcv1

となります。

Bishop向けLinuxカーネルのテスト版 - 2.6.24-rc6

Posted by Seiichi SATO

Bishop向けLinuxカーネルのテスト版 (2.6.24-rc6) を公開します。

最新版は2.6.26.8です。記事: Bishop向けLinuxカーネルのテスト版 - 2.6.26.8

主な変更点は以下の通りです。

  • 2.6.22.1から2.6.24-rc6へ
  • initrdからinitramfsへ変更
  • エミュレータ上の開発用仮想ターゲットPE-201Qに対応

本カーネルは近日中に正式リリースされる予定です。今後出荷するBishopにもプリインストールされます。これまでご購入いただいたお客様につきましては、アップデート手順をご案内させていただきます。

関連記事

klibcベースのinitramfs

Posted by Seiichi SATO

写真 (rootfs_chooser_screenshot.jpg)

Bishopにプリインストールされている uClibcベースのinitrdを klibcによるinitramfsに変更する予定です。

klibcやinitramfsについては、カーネル付属文書Documentation/early-userspace/READMEを参照してください。JFプロジェクトによる日本語訳もあります。

klibcのサンプル実装として、起動時にタッチスクリーンからルートファイルシステムを選択する仕組みを用意しました。

起動時に表示される画面上のアイコンをタッチすることにより、NAND、NFS、USBマスストレージ、SDカードの何れかからルートファイルシステムを選択できます。

近日中にリリース予定のBishop向けカーネルでは、このカスタムinitramfsも含まれます。

クロス開発環境のRPMパッケージ

Posted by Seiichi SATO

クロス開発環境のDebianパッケージalien で変換したRPMパッケージを 公開します。

概要

クロス開発環境のDebianパッケージ を参照してください。

対応状況

クロス開発環境のDebianパッケージ を参照してください。

yumによるインストール (Fedora)

以下の内容で/etc/yum.repos.d/pylone-jp.repoを作成して、yumレポジトリを追加します。

[cross-toolchain]
name=Cross Toolchain
baseurl=http://downloads.pylone.jp/cross-toolchain/rpm/
enabled=1
gpgcheck=0

レポジトリ情報を更新します。

# yum update

必要なツールをインストールします。ARCHは arm、mipsel、sh4、powerpc の何れかに置き換えてください。

gcc-3.4
# yum install gcc-3.4-ARCH-linux-gnu
gcc-4.1
# yum install gcc-4.1-ARCH-linux-gnu
g++-4.1
# yum install g++-4.1-ARCH-linux-gnu
gdb
# yum install gdb-ARCH-linux-gnu

依存関係について

alienによる変換ではパッケージ間の依存関係が失われますが、 本パッケージではspecファイルを修正して依存関係を追加しています。

更新履歴

  • 2007/12/12: 公開

initramfs作成支援スクリプト

Posted by MINAMI Hirokazu

About

Linux起動時にinitramfsを使用するためには、以下のいずれかを用意する必要があります。

  • 所定の形式のcpioアーカイブ
  • 展開済みのディレクトリ
  • usr/gen_init_cpio 用の設定スクリプト

このうち「usr/gen_init_cpio用の設定スクリプト」を使えると、ユーザ権限で作業ができるため、作業環境の扱いが簡単になります。

しかし、きちんと(間接的に必要となるライブラリ等まで考慮して)スクリプトを記述するのはそれなりの手間がかかり、使いこなすには経験が必要でした。

この作業の支援用として、実行可能ファイルに必要なライブラリ等の情報を抽出して設定スクリプトの雛形を生成するツールを公開します。

使いかた

ダウンロード

以下のリンク先から取得してください:

gen_init_cpio_conf.py

実行には python および binutils が必要です。

前準備

適当なディレクトリ以下に、initramfsに含めたいファイルを全て展開します。この段階では不要なファイルが含まれていても構わないので、手順としては

  1. 関連するパッケージを dpkg -x で展開
  2. その他のファイルをコピー

などとすればよいでしょう。

設定ファイル作成

最終的にinitramfsに含めたいファイルのリストを用意します。

例)FOO.def として

/bin/busybox
/bin/brcrl

誤認識されないなら、パスのディレクトリ部分(/usr/bin)は省略することができます。

busybox
brctl
スクリプトの実行

本スクリプトを「-l」 オプションにファイルリスト、続けて作業用の(ファイル一式を展開しておいた)ディレクトリのフルパスを指定して実行すると、initramfs用の設定内容が作成されます。

$ gen_init_cpip_conf.py -l FOO.def /path/to/work/dir  > initramfs_script

作業用ディレクトリには、Linuxカーネル構築時に正しく参照が解決できるなら、相対パスを使用することもできます。

可視化

例えば、busybox, Xサーバ, matchbox について、実行に必要なライブラリとシンボリックリンクの関係は以下のようになりました。

[image] (deptree.png)

高解像度版 (PNG)原図 (SVG)

クロス開発環境のDebianパッケージ

Posted by Seiichi SATO

社内で使っているクロス開発環境のDebianパッケージを公開します。

更新履歴

  • 2007/11/09: 公開
  • 2007/12/15: apt-lineのtypoを修正
  • 2008/02/26: update-alternativesについての記述を追加
  • 2008/07/04: mipsel で gcc-4.1 の動作を確認
  • 2008/12/22: アーカイブの鍵についての記述を追加
  • 2009/03/09: powerpc で動作を確認

概要

  • ホストアーキテクチャ: i386
  • ターゲットアーキテクチャ: arm, mipsel, powerpc, sh4
  • コンパイラ: gcc-3.4, gcc-4.1, g++-4.1
  • glibc: 2.3.6 (etch の glibc)
  • ssp: 無効

基本的にはetchのbinutils, gccをdebian/README.cross等の手順通りにビルドしたものですが、etchとsidの両方にインストールできるように依存関係を調整するなど若干の変更を加えています。

対応状況

gcc-3.4gcc-4.1g++-4.1
arm
mipsel
powerpc××
sh4
  • ○:動作を確認したもの
  • △:パッケージはあるが、まだ動作が確認できていないもの
  • ×:まだパッケージが用意できていないもの

インストール

etchかsidであればインストールできる筈です。

/etc/apt/sources.listに以下のapt lineを加えます。

deb http://downloads.pylone.jp/cross-toolchain/deb ./

アーカイブの鍵を導入します。

# wget http://pylone.jp/pubkey.asc -O - | apt-key add -

パッケージ情報を更新します。

# aptitude update

必要なツールをインストールします。ARCHはarm、mipsel、sh4、powerpcの何れかに置き換えてください。

gcc-3.4
# aptitude install gcc-3.4-ARCH-linux-gnu
gcc-4.1
# aptitude install gcc-4.1-ARCH-linux-gnu
g++-4.1
# aptitude install g++-4.1-ARCH-linux-gnu
※ powerpc用g++はまだ用意できていません。
gdb
# aptitude install gdb-ARCH-linux-gnu
gcc-3.4とgcc-4.1の切り替え
# update-alternatives --config ARCH-linux-gnu-gcc

リンク

謝辞

sh4用glibcをビルドするにあたって、シリコンリナックス株式会社様が公開されているglibcパッケージのdebian/patches/sh/*.diffを使わせて頂きました。

ディスクイメージのホスト側での操作方法

Posted by MINAMI Hirokazu

QEMUなどのシステムエミュレータでは、エミュレートされるシステムに対して仮想的なデバイスを見せることができます。 ハードディスクなどの記憶装置を模擬する場合、ディスクイメージをファイルとして作成して使うことが多いでしょう。

今回は、このディスクイメージを仮想環境の外側で作成/操作する手段について紹介します。

作業環境としてはLinuxを想定しています。

イメージの作成

希望の構成のディスクイメージを、ホスト環境で作成する手順を説明します。

ファイル作成

まず希望のデバイスサイズのファイルを用意します。

サイズさえ十分ならどのようにしても構いませんが、ddで作ることをおすすめします。例えば 512 MBytes のものを作りたいなら

$ dd if=/dev/zero of=FILENAME bs=1 count=1 seek=536870911

とするとよいでしょう。(seek= の値は、512 MBytes = 524288 KBytes = 536870912 Byte なので、536870912-1 を指定しています)

素朴に /dev/zero からコピーして

$ dd if=/dev/zero of=FILENAME bs=1M count=512

としてもよいのですが、近代的な(ファイルにholeが作れる)ファイルシステムで作業しているならseek させた方が終了が早く、実ディスク消費も抑えられます。

パーティション作成

エミュレーションされる環境を実際の環境に近付けるために、ディスクイメージ上にはパーティションが作成されている状態を用意できると便利です。そこで、ループバックデバイスを用いてファイルをブロックデバイスとして見せ、fdisk などの対象に取れるようにする方法について説明します。

パーティションを作成する必要がないなら、ディスクイメージに対してmkfsを実行すれば十分なので、この節の内容は不要です。

まず、losetupを用いてファイルをループバックデバイスに結びつけます。この操作にはroot権限が必要です。

# losetup /dev/loop0 FILENAME

losetupに成功すると、/dev/loop0がFILENAMEを内容とするブロックデバイスとして振る舞うようになります。

何らかの理由でloop0が使用中の場合は、適宜loop1などに読みかえてください。

ループバックデバイスに対してfdiskを実行します。後の作業で各パーティションの開始セクタ番号が必要になるので、-uオプションを付けておきます。

# fdisk -u /dev/loop0
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0xaf87fef0.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

パーティションを作成します。この例では一つだけ作ります。

Command (m for help): n
First sector (63-1048575, default 63):
Using default value 63
Last sector or +size or +sizeM or +sizeK (63-1048575, default 1048575):
Using default value 1048575

パーティションを作成したら、状態を確認します。

Command (m for help): p

Disk /dev/loop0: 536 MB, 536870912 bytes
255 heads, 63 sectors/track, 65 cylinders, total 1048576 sectors
Units = sectors of 1 * 512 = 512 bytes
Disk identifier: 0xaf87fef0

      Device Boot      Start         End      Blocks   Id  System
/dev/loop0p1              63     1048575      524256+  83  Linux
Partition 1 does not end on cylinder boundary.

表示される値のうち、「Units」の値(ここでは 512 bytes)と「Start」の値(ここでは63)を覚えておきます。

作成結果に問題なければ変更をイメージに書き戻して終了します。

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 22: Invalid argument.
The kernel still uses the old table.
The new table will be used at the next reboot.
Syncing disks.
Command (m for help): q

使いおわったらループバックデバイスを開放します。

# losetup -d /dev/loop0
イメージ内のパーティションをフォーマット

ここまでの作業でディスクイメージにパーティションを作成できましたが、まだ個々のパーティションにはファイルシステムが書かれていません。個別のパーティションに対してmkfsを実行するための手順を説明します。

mkfsの対象とするためには、(ディスクイメージ全体ではなく)対象となるパーティションの部分を取り出す必要があります。

losetupの-oオプションを使用することで、ファイルの途中からをループバックデバイスに結びつけます。

先ほどの例では 開始位置が 63、Unit が 512 bytes だったので、パーティション#1のオフセットとして63*512=32256バイトを設定します。

# losetup -o 32256 /dev/loop0 FILENAME

losetupに成功したら、好みのファイルシステムを作成できます。

# mkfs.ext2 /dev/loop0

使いおわったらループバックデバイスを開放します。

# losetup -d /dev/loop0

イメージ内のパーティションに外からアクセス

既にファイルシステムが作られているイメージ(上記の手順で作成したものや、仮想環境で使っていたrawイメージなど)を扱う場合、mountの"loop"オプションを使用することで、イメージ内部のパーティションを直接ホスト環境にマウントすることができます。

この例の場合、loopのoffsetに開始位置(32256)を指定する:

# mount -o loop,offset=32256 FILENAME /mnt/

と、/mnt経由で先ほど作成したパーティションの内容を操作することができるようになります。

作業が終わったら通常のmountと同じように

# umount /mnt/

します。

注意

仮想環境で使用中のイメージファイルをホスト側環境から同時に操作すると、データを失う可能性があります。

sysfs 経由でモジュールパラメータにアクセス

Posted by Seiichi SATO

sysfs経由でモジュールパラメータにアクセスする方法を紹介します。

Linux-2.6でモジュールパラメータを定義するマクロがMODULE_PARMからmodule_paramに変更されました。

Linux-2.4のMODULE_PARM:

/* パラメータparamをint型で宣言 */
static int param = 0;
MODULE_PARM(param, "i");
MODULE_PARM_DESC(param, "Description");

Linux-2.6のmodule_param:

/* パラメータparamをint型で宣言 */
static int param = 0;
module_param(param, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(param, "Description");

insmodの引数として指定できるパラメータであることは同じですが、module_paramではsysfsからもパラメータにアクセスできます。

# echo 1 > /sys/module/モジュール名/parameters/param

似たようなことはprocfsでもできますが面倒です。module_paramであればsysfsの詳細を知らなくても定義するだけでモジュール内の変数をパラメータとしてユーザ空間にexportできます。デバッグ時など、ioctlを使うまでもない場合には便利じゃないでしょうか?

モジュールではなくカーネルにstaticリンクされててもアクセスできます。

sysfsによってファイルとして見えるパラメータのパーミッションはmodule_paramの引数で指定します。

パラメータとして使う変数が文字列の場合、module_param_string を使います。

関連記事

Linux 起動ロゴの変更

Posted by Seiichi SATO

フレームバッファに表示される起動時のロゴ画像を変更する方法を紹介します。

screenshot (fdo_logo_screenshot.jpg)

以前はピクセル値が配列にベタ書きされたヘッダファイルを用意する必要がありましたが、Linux-2.6でフレームバッファ周辺が書き直されて PNM を直接ソースツリーに置けるようになりました。

ロゴ画像 (fdo_logo.png)

例として、このfreedesktop.orgのロゴ画像 (PNG, 80x80) を224色の起動ロゴにしてみます。

まず、画像をPNMに変換します。

$ convert -colors 224 fdo_logo.png fdo_logo.pnm

pnm2ascで ピクセル値がASCIIのPNMに変換して、drivers/video/logo/ に放り込みます。

$ pnm2asc fdo_logo.pnm > drivers/video/logo/logo_fdo_clut224.ppm

drivers/video/logo/Makefileに以下を追加します。

obj-$(CONFIG_LOGO_FDO_CLUT224) += logo_fdo_clut224.o

drivers/video/logo/Kconfig に以下を追加します。

config LOGO_FDO_CLUT224
        bool "224-color freedesktop.org logo"
        depends on LOGO
        default y

drivers/video/logo/logo.cに追加したロゴ画像のプロトタイプ宣言を加えます。

extern const struct linux_logo logo_fdo_clut224;

drivers/video/logo/logo.c:fb_find_logo()のif (depth >=4) { } の最後に以下を追加します。

#ifdef CONFIG_LOGO_FDO_CLUT224
logo = &logo_fdo_clut224;
#endif

あとは、CONFIG_LOGO_FDO_CLUT224=yでカーネルをリビルドするだけです。

drivers/video/logo/{Makefile,Kconfig,logo.c}を弄りたくなければ、既存のロゴを上書きするだけでもいいと思います。

top
[0] ホーム
[4] 記事一覧
© 2010 Pylone
会社概要 | プライバシー