2009-06-04 9 views
44

私はUbuntuの下でカスタムカーネルをコンパイルしています。カーネルがどこでファームウェアを探すべきかわからないという問題が発生しています。 Ubuntu 8.04の下では、ファームウェアはドライバモジュールと同じ方法でカーネルバージョンに結びついています。私は応じ2.6.24-24-ジェネリックUbuntuのカーネルをコンパイルLinuxカーネルはドライバのファームウェアを探す場所をどのように知っていますか?

/lib/firmware/2.6.24-24-generic 

:たとえば、カーネル2.6.24-24-一般的な店舗でのカーネルモジュール:

/lib/modules/2.6.24-24-generic 

とでそのファームウェア「Alternate Build Method: The Old-Fashioned Debian Way」適切なモジュールディレクトリがあり、私のIntelワイヤレスカード(ipw2200モジュール)などのファームウェアが必要なものを除き、すべてのデバイスが機能します。

カーネルログはipw2200ファームウェアをロードしようとすると、ファームウェアのローディングを制御するカーネル・サブシステムがそれを見つけることができないことを例えば示す:

ipw2200: Detected Intel PRO/Wireless 2200BG Network Connection 
ipw2200: ipw2200-bss.fw request_firmware failed: Reason -2 

errnoに-base.hは、これを定義します

#define ENOENT  2 /* No such file or directory */ 

(ENOENTを返す関数は、その前にマイナスを置きます。)

私はカーネルの名前が指摘/ libに/ファームウェアでシンボリックリンクを作成してみましたしかし2.6.24-24ジェネリックディレクトリにも同じエラーが発生しました。このファームウェアは、インテルが提供し、Ubuntuによってパックされた非GPLです。私はそれが特定のカーネルバージョンとの実際のつながりを持っているとは思わない。 cmpは、さまざまなディレクトリのバージョンが同一であることを示しています。

カーネルはどのようにファームウェアを探すべきかを知っていますか?

更新

私は、しかし、それはもはやUbuntuは/etc/hotplug.dを排除しているように動作し、もはや/usr/lib/hotplug/firmwareにそのファームウェアを格納し、私がいる正確な問題にthis solutionは認められませんでした。

アップデート2

いくつかのより多くの研究は、いくつかのより多くの答えを上げ。 udevのバージョン92まで、プログラムfirmware_helperがファームウェアのロード方法でした。 udev 93で始まるこのプログラムは、私が知る限り同じ機能を提供するfirmware.shという名前のスクリプトに置き換えられました。両方とも、ファームウェアパスを/lib/firmwareにハードコードします。 Ubuntuはまだ/lib/udev/firmware_helperバイナリを使用しているようです。

ファームウェアファイルの名前は、環境変数$FIRMWAREfirmware_helperに渡され、/lib/firmwareのパスに連結され、ファームウェアのロードに使用されます。

ファームウェアをロードするために、実際の要求は、システムコールを介してドライバ(私の場合はipw2200)によって構成されています。どこか$FIRMWARE環境変数を見てrequest_firmwarefirmware_helperを呼び出すドライバーの間で今

request_firmware(..., "ipw2200-bss.fw", ...); 

、カーネルパッケージ名がファームウェア名の前に追加されています。

誰がやっているのですか?

+0

誰かがこの質問を閉じるために投票した理由を説明するコメントを追加できますか?フィードバックに感謝します。 –

+2

「serverfault.comに所属している」ため、投票の投票が行われています。それはプログラミングに関するものではなく、むしろ管理に関するものであるため、これは両方のサイトの使命に関する記述と一致しています。 – ephemient

+0

フィードバックいただきありがとうございます。カスタムカーネルを構築しようとしているときに問題が発生していたので、これをプログラミングの問題と考えていました。なぜ私はいくつかの良い推測があると思うが、誰かがこれをプログラミング関連ではないと考える理由を知りたいのですが。 –

答えて

38

、参照/usr/src/linux/Documentation/firmware_class/README

 
kernel(driver): calls request_firmware(&fw_entry, $FIRMWARE, device) 

userspace: 
     - /sys/class/firmware/xxx/{loading,data} appear. 
     - hotplug gets called with a firmware identifier in $FIRMWARE 
      and the usual hotplug environment. 
       - hotplug: echo 1 > /sys/class/firmware/xxx/loading 

kernel: Discard any previous partial load. 

userspace: 
       - hotplug: cat appropriate_firmware_image > \ 
             /sys/class/firmware/xxx/data 

kernel: grows a buffer in PAGE_SIZE increments to hold the image as it 
     comes in. 

userspace: 
       - hotplug: echo 0 > /sys/class/firmware/xxx/loading 

kernel: request_firmware() returns and the driver has the firmware 
     image in fw_entry->{data,size}. If something went wrong 
     request_firmware() returns non-zero and fw_entry is set to 
     NULL. 

kernel(driver): Driver code calls release_firmware(fw_entry) releasing 
       the firmware image and any related resource. 

カーネルは実際にはまったくファームウェアをロードしません。ユーザスペースに「xxxという名前のファームウェアが必要です」というメッセージが表示され、ユーザスペースがファームウェアイメージをカーネルに戻すのを待ちます。あなたが発見したように

は今、Ubuntuの8.04、

 
$ grep firmware /etc/udev/rules.d/80-program.rules 
# Load firmware on demand 
SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware_helper" 

に、udevは、カーネルは、ファームウェアを要求するときfirmware_helperを実行するように設定されています。

 
$ apt-get source udev 
Reading package lists... Done 
Building dependency tree 
Reading state information... Done 
Need to get 312kB of source archives. 
Get:1 http://us.archive.ubuntu.com hardy-security/main udev 117-8ubuntu0.2 (dsc) [716B] 
Get:2 http://us.archive.ubuntu.com hardy-security/main udev 117-8ubuntu0.2 (tar) [245kB] 
Get:3 http://us.archive.ubuntu.com hardy-security/main udev 117-8ubuntu0.2 (diff) [65.7kB] 
Fetched 312kB in 1s (223kB/s) 
gpg: Signature made Tue 14 Apr 2009 05:31:34 PM EDT using DSA key ID 17063E6D 
gpg: Can't check signature: public key not found 
dpkg-source: extracting udev in udev-117 
dpkg-source: unpacking udev_117.orig.tar.gz 
dpkg-source: applying ./udev_117-8ubuntu0.2.diff.gz 
$ cd udev-117/ 
$ cat debian/patches/80-extras-firmware.patch 

あなたがソースを読めば、あなたはUbuntuは/lib/modules/$FIRMWARE、その後、/lib/modules/$(uname -r)/$FIRMWAREのために初見にハードコードされているfirmware_helperを書いていないし、他の場所ことがわかります。

echo -n 1 > /sys/$DEVPATH/loading 
cat /lib/firmware/$(uname -r)/$FIRMWARE > /sys/$DEVPATH/data \ 
    || cat /lib/firmware/$FIRMWARE  > /sys/$DEVPATH/data 
if [ $? = 0 ]; then 
    echo -n 1 > /sys/$DEVPATH/loading 
    echo -n -1 > /sys/$DEVPATH/loading 
fi 

正確にカーネルが期待する形式である:shにそれを翻訳、それはおよそこれを行います。


長い話を短くするには:Ubuntuのudevパッケージは、常に最初の/lib/firmware/$(uname -r)で見てカスタマイズされています。このポリシーはユーザー空間で処理されています。

+1

素敵な答え、ありがとう!私は、Ubuntuのソースを見て、Ubuntuの 'firmware_helper'がどこから来ているのか把握しようとしていました。 udevソースツリー内のファームウェアに対して再帰的なgrepを実行したばかりである。 –

+0

実際はおそらくudev-extrasツリーから、Ubuntuがudevパッケージを修正してバンドルすることを決めた部分があります。 – ephemient

+0

'apt-get source'はパッケージのDebian(またはUbuntu)ソースツリーをダウンロードして解凍します。パッケージにはパッケージ情報と配布固有の設定を持つ' debian'ディレクトリがあり、上流に見つからないパッチが含まれることがあります。これがその例です。 – ephemient

1

現在のLinuxシステムでは、udevfirmware.agentで処理されます。カーネルの観点から

+0

Ubuntu 8.04には、udevにfirmware.agentがありません。それにはfirmware_helperというものがあります。いずれにせよ、これはカーネルにファームウェアをどこに見つけるかをどのように伝えるのでしょうか? –

+0

udevが呼び出すコマンドは、ファームウェアをカーネルにロードする役割を担います。 Debianのfirmware.agentを読んでから、/ sysの特別なファイルにファームウェアを書き込みます。 –

11

これは非常に有用な情報であり、ファームウェアを必要とするデバイス向けのカスタムUSBカーネルモジュールを作成する際に私の問題の解決に導いてくれました。

基本的に、すべてのUbuntuは、hal、sysfs、devfs、udevなどの新しい再ハッシュをもたらします。実際に私は彼らがhalを使って停止したことを読んだ。

これをリバースエンジニアリングして、最新の[Ubuntu]システムに関係するようにしましょう。

Ubuntu Lucid(最新の書き込み時)には、/lib/udev/rules.d/50-firmware.rulesが使用されています。このファイルはバイナリ/lib/udev/firmwareを呼び出し、魔法が発生します。

リスト:/lib/udev/rules.d/50-firmware。ルール

# firmware-class requests, copies files into the kernel 
SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware --firmware=$env{FIRMWARE} --devpath=$env{DEVPATH}" 

魔法はこれらの線に沿って何かする必要があります

(ソース: Linux Device Drivers, 3rd Ed., Ch. 14: The Linux Device Model):

  • は、1 loadingから
  • コピーファームウェア失敗した場合にdata
  • にエコーエコー-1へloadingおよびファームウェアのロード処理を中止する
  • エコー0〜loading(その後、
  • )カーネルを知らせる、特定のカーネルモジュールは、udev-151/extras/firmware/firmware.cに、そのファームウェア/ libに/ udevのためのソースを、データを受信して​​、あなたはudevのための明晰のソースページを見れば、デバイス

にそれをプッシュします/ firmwareバイナリ、これはまさにそれです。

抜粋:明晰ソース、udevの-151 /エクストラ/ファームウェア/ firmware.c

util_strscpyl(datapath, sizeof(datapath), udev_get_sys_path(udev), devpath, "/data", NULL); 
    if (!copy_firmware(udev, fwpath, datapath, statbuf.st_size)) { 
      err(udev, "error sending firmware '%s' to device\n", firmware); 
      set_loading(udev, loadpath, "-1"); 
      rc = 4; 
      goto exit; 
    }; 

    set_loading(udev, loadpath, "0"); 

さらに、多くのデバイスは、私が持っている(これをウィキ(textishファイルはチェックサムや他のものを含む)インテルHEXフォーマットを使用します評判はなく、リンクする能力もない)。カーネルプログラムihex2fw(.HEXファイルのkernel_source/lib/firmwareのMakefileから呼び出される)は、これらのHEXファイルを、Linuxカーネルがrequest_ihex_firmwareでピックアップする任意の設計のバイナリ形式に変換します。愚かな(それは物事を遅らせるだろう)。

+1

+1あなたは何人かの代理人がいて、リンクすることができます。 OPや他の人の回答が役に立つと分かった場合は、投票してください。 –

1

Linux 3.5.7 Gentoo、私は同じ問題があります。 は解決:

emerge ipw2200-firmware 

はその後、デバイスドライバには/ usr/src/linuxの

make menucofig 

に行くすべてのwirlessのドライバがモジュールとしてIntell 2200に設定して再コンパイルし、必要はありません削除します。

make 
make modules_install 
cp arch/x86/boot/bzImage /boot/kernel-yourdefault