54

Ubuntuでカスタムカーネルをコンパイルしていますが、カーネルがファームウェアを探す場所を認識していないように見えるという問題が発生しています。Ubuntu 8.04では、ファームウェアはドライバーモジュールと同じようにカーネルバージョンに関連付けられています。たとえば、kernel 2.6.24-24-genericは、カーネルモジュールを次の場所に格納します。

/lib/modules/2.6.24-24-generic

およびそのファームウェア:

/lib/firmware/2.6.24-24-generic

「代替ビルド方法:昔ながらのDebianWay」に従って2.6.24-24-genericUbuntuカーネルをコンパイルすると、適切なモジュールディレクトリが取得され、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を返す関数は、その前にマイナスを置きます。)

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

では、カーネルはどのようにしてファームウェアを探す場所を知るのでしょうか?

アップデート

私が抱えている問題に対するこの解決策を見つけましたが、Ubuntuが排除され/etc/hotplug.d、ファームウェアがに保存されなくなったため、機能しなくなりました/usr/lib/hotplug/firmware

Update2

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

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

ファームウェアをロードする実際の要求は、システムコールを介してドライバー(私の場合はipw2200)によって行われます。

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

これで、ドライバーが環境変数を呼び出して確認する間のどこかでrequest_firmware、カーネルパッケージ名がファームウェア名の前に追加されます。firmware_helper$FIRMWARE

それで、誰がそれをしているのですか?

4

4 に答える 4

42

カーネルの観点からは、/ usr / src / linux / Documentation /firmware_class/READMEを参照してください。

kernel(driver):request_firmware(&fw_entry、$ FIRMWARE、device)を呼び出します

 ユーザースペース:
        -/ sys / class /firmware / xxx / {loading、data}が表示されます。
        --hotplugは$FIRMWAREのファームウェア識別子で呼び出されます
          そして通常のホットプラグ環境。
                -ホットプラグ:echo 1> / sys / class / Firmware / xxx / reading

 カーネル:以前の部分的なロードを破棄します。

 ユーザースペース:
                -ホットプラグ:catproperty_firmware_image> \
                                        / sys / class /firmware / xxx / data

 カーネル:バッファをPAGE_SIZE単位で拡張して、イメージをそのまま保持します
         入って来る。

 ユーザースペース:
                -ホットプラグ:echo 0> / sys / class / Firmware / xxx / Loading

 カーネル:request_firmware()が返され、ドライバーにファームウェアがあります
         fw_entry-> {data、size}の画像。何かがうまくいかなかった場合
         request_firmware()はゼロ以外を返し、fw_entryはに設定されます
         ヌル。

 kernel(driver):ドライバーコードはrelease_firmware(fw_entry)リリースを呼び出します
                 ファームウェアイメージと関連リソース。

カーネルは実際にはファームウェアをまったくロードしません。「 xxxという名前のファームウェアが欲しい」とユーザースペースに通知し、ユーザースペースがファームウェアイメージをカーネルにパイプで戻すのを待ちます。

さて、Ubuntu 8.04では、

$grepファームウェア/etc/udev/rules.d/80-program.rules
#オンデマンドでファームウェアをロードする
SUBSYSTEM == "firmware"、ACTION == "add"、RUN + = "firmware_helper"

あなたが発見したように、カーネルがファームウェアを要求したときudevに実行するように構成されています。firmware_helper

$ apt-get source udev
パッケージリストを読んでいます...完了
依存関係ツリーの構築
状態情報を読み取っています...完了
312kBのソースアーカイブを取得する必要があります。
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]
1秒で312kBをフェッチ(223kB / s)
gpg:署名は2009年4月14日火曜日05:31:34PMEDTでDSAキーID17063E6Dを使用して作成されました
gpg:署名を確認できません:公開鍵が見つかりません
dpkg-source:udev-117でudevを抽出
dpkg-source:udev_117.orig.tar.gzを解凍します
dpkg-source:./udev_117-8ubuntu0.2.diff.gzを適用します
$ cd udev-117 /
$ cat debian / patchs / 80-extras-firmware.patch

ソースを読むと、Ubuntuが、最初に、次に、firmware_helperを検索するようにハードコードされたを作成し、他の場所は作成していないことがわかります。これをに変換すると、ほぼ次のようになります。/lib/modules/$(uname -r)/$FIRMWARE/lib/modules/$FIRMWAREsh

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

これはまさにカーネルが期待するフォーマットです。


簡単に言うと、Ubuntuのudevパッケージには、常に/lib/firmware/$(uname -r)最初に調べるカスタマイズが含まれています。このポリシーはユーザースペースで処理されています。

于 2009-06-04T22:15:23.893 に答える
14

これは非常に有用な情報であり、ファームウェアを必要とするデバイス用のカスタム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.rules

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

魔法はこれらの線に沿ったものでなければなりません(出典:Linuxデバイスドライバー、第3版、第14章:Linuxデバイスモデル):

  • エコー1からloading
  • ファームウェアをにコピーしますdata
  • 失敗した場合は、-1をエコーし​​てloadingファームウェアのロードプロセスを停止します
  • 0をエコーし​​てloading(カーネルに信号を送る)
  • 次に、特定のカーネルモジュールがデータを受信し、それをデバイスにプッシュします

Lucidのudevのソースページを見るとudev-151/extras/firmware/firmware.c、そのファームウェア/ lib / udev/firmwareバイナリのソースがまさにその通りになっています。

抜粋:明快なソース、udev-151 / extras /firmware /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");

さらに、多くのデバイスはIntel HEX形式(チェックサムやその他のものを含むテキストファイル)を使用します(wiki itには評判がなく、リンクする機能もありません)。カーネルプログラムihex2fw(.HEXファイルのkernel_source / lib /firmwareのMakefileから呼び出されます)は、これらのHEXファイルを任意に設計されたバイナリ形式に変換しrequest_ihex_firmwareます。 (それは物事を遅くします)。

于 2010-06-10T07:04:55.813 に答える
1

現在のLinuxシステムでは、これはとを介して処理されudevますfirmware.agent

于 2009-06-04T12:12:18.233 に答える
1

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

emerge ipw2200-firmware

次に、/ usr / src/linuxに移動します

make menucofig

デバイスドライバで、不要なワイヤレスドライバをすべて削除し、Intell2200をモジュールとして設定して再コンパイルします。

make
make modules_install
cp arch/x86/boot/bzImage /boot/kernel-yourdefault
于 2013-02-26T09:59:13.577 に答える