Linux では、ファームウェアは「ファームウェア」を指します。ファームウェアは、ハードウェア デバイス自体によって実行されるプログラムであり、通常はデバイスのフラッシュに保存されます。 Linux システムでは、デバイス ドライバーはカーネル状態にあり、ファームウェア ファイルはユーザー状態にあるため、デバイス ドライバーがファームウェア ファイルを正常にロードするには、安全で安定した信頼性の高いメカニズムが必要です。
#このチュートリアルの動作環境: linux7.3 システム、Dell G3 コンピューター。
Linuxファームウェアとは
ファームウェア(ファームウェア)とは、ハードウェアデバイス自体によって実行されるプログラムです。ファームウェアは通常、デバイスのフラッシュに保存されます。コストと利便性の理由から、ハードウェア デバイスの実行プログラムは通常、特定の形式のファームウェア ファイルにパッケージ化され、端末システムに保存され、ハードウェア デバイスは端末システムを通じてアップグレードされます。
Linux カーネル開発プロセス中、開発者は、タッチ、充電、リニア モーター、ストレージ、WIFI デバイスなどの周辺ドライバー デバイスをデバッグします。また、ファームウェアの更新が必要な状況もあります。 Linux システムでは、デバイス ドライバーはカーネル状態にあり、ファームウェア ファイルはユーザー状態にあるため、デバイス ドライバーがファームウェア ファイルを正常にロードするには、安全で安定した信頼性の高いメカニズムが必要です。
デバイス ドライバーがカーネル モードからユーザー モード ファームウェア ファイルを安定して読み込むという問題を解決するために、Linux システムはファームウェア サブシステムを提供します。
Linux ファームウェア サブシステム プロセスの紹介
Linux ファームウェア サブシステムは、sysfs および uevent メカニズムに基づいて実装されます。
ドライバーがファームウェア システム関数インターフェイスを呼び出してファームウェアを適用した後、ファームウェア サブシステムはファームウェア コンパイル カーネルを使用してファームウェアを取得します。取得が失敗した場合は、ファームウェア キャッシュを使用してファームウェアを取得します。それでも取得できない場合は、デフォルト パス カーネルを使用して直接検索してファームウェアを取得します。それでも取得が失敗する場合は、uevent メッセージを init プロセスに報告します。 init プロセスは uevent メッセージを受信し、サブシステム タイプがファームウェアであるメッセージをフィルターで除外します。 init プロセスは、uevent メッセージで指定されたファームウェア情報に基づいてファームウェアを検索し、取得したファームウェアの内容を、sysfs が提供するファイル ノード インターフェイスを介してユーザー状態からカーネル状態に書き込み、ドライバーがデータを取得できるようにします。ファームウェアファイルの。
Linux ファームウェア システムは、さまざまなシナリオでファームウェア ファイルを取得するためのさまざまな方法を提供します。
1) カーネルに直接コンパイルする方法;
2) ファームウェアをキャッシュする方法;
3) カーネルに合わせてパスを直接指定する方法:
4) init プロセスを通じて処理を支援;
Linux ファームウェア サブシステムのフローチャート
##Linux ファームウェア サブシステムのメイン関数インターフェイス
メイン関数インターフェイス:アプリケーション ファームウェア インターフェイスの主なタイプは、同期インターフェイスと同期インターフェイスに分けられます。非同期。 通常、ファームウェアの適用プロセスには時間がかかり、ファームウェアのアップグレードの処理プロセスにも時間がかかるため、非同期関数インターフェイスを使用して実装するか、最初にドライバーでワーク キューを作成します。そしてそれを実装するために同期関数インターフェースを呼び出します。 その例:#Linux ファームウェア サブシステム実装プロセス
request_firmware 実装プロセスrequest_firmware 関数は、_request_firmware_prepare 関数を呼び出してさまざまなフラグ ビットを設定し、さまざまな差分機能を実現します。
次に、 fw_lookup_and_allocate_buf 関数を呼び出して、グローバル fw_cache 構造内のリンク リストに現在要求されているファームウェアの名前が記録されているかどうかを確認します。現在要求されているファームウェアの名前が存在しない場合、対応するメモリ空間が動的に割り当てられ、現在要求されているファームウェアの名前がグローバル fw_cache 構造体のリンク リストに追加されます。
fw_get_filesystem_firmware 関数
主に、カーネルによって提供されるデフォルトのパスを通じてファームウェア ファイルを検索し、kernel_read_file_from_path 関数を呼び出します。ファームウェア ファイルが見つからない場合は、フラグ ビット FW_OPT_USERHELPER を使用して USER_HELPER モードが有効かどうかを判断します。
その中に:
ファームウェア システムのデフォルト パスは次のとおりです:
デフォルト パスはカーネルを通じて追加できます。コマンドライン module_param_string インターフェイスを変数パスに渡して、新しいパスをカスタマイズします。
USER_HELPER モード
この関数は、カーネルが CONFIG_FW_LOADER_USER_HELPER をオンにした後にのみサポートされます。主な機能は、カーネルを通じて uevent メッセージを init プロセスに報告し、init プロセスを通じてファームウェア情報を取得し、それを基礎となる sysfs ノードに書き込むことです。
fw_load_from_user_helper 関数:
最初に fw_create_instance 関数を呼び出して、デバイス device、クラス ファイル、および属性ファイルを作成し、firmware_priv 構造体を割り当てます。
次に、/sys/class/firmware の下にディレクトリが作成されます。このディレクトリでは、デバイス名がディレクトリ名として使用されます。
このディレクトリには 3 つの属性が含まれています:
loading:
は 1 に設定されます: この属性は、担当するユーザー空間で 1 を設定することで開始されます。ファームウェアのロード;
は 0 に設定されます: ロード プロセスが完了したとき;
は -1 に設定されます: ファームウェアのロード プロセスは終了します。
#data:
はファームウェア データの受信に使用されます。ロードが設定された後、ユーザー空間プロセスはファームウェアをこの属性に書き込みます。
device:
/sys/devices にある対応するエントリのシンボリック リンク。
timeout:
uevent を介してファームウェアを適用する場合のデフォルトの最大タイムアウトは 60 秒で、上位層の書き込みタイムアウトがサポートされています。
_request_firmware_load 関数:
最初に uevent レポートを無効にし、device_add 関数を呼び出してデバイスを追加し、firmware_uevent 関数の呼び出しをトリガーします。その中に、ファームウェアの名前、タイムアウト期間、非同期かどうかなど、uevent によって報告される情報形式を記入します。
次のステップでは、uevent レポート関数を有効にし、同時に kobject_uevent 関数を呼び出し、追加アクション タイプを上位層 ueventd にレポートします。
その後、fw_state_wait_timeout 関数を呼び出し、あらかじめ設定されたタイムアウト期間内に上位層 ueventd の処理を待ちます。
タイムアウトに達するか、完了量の受信後にウェイクアップすると、以前に適用されていたメモリが解放され、デバイスやクラスなどのメモリ情報が解放されます。
ueventd 関連のファームウェア処理プロセス
ueventd は init プロセスの重要なモジュールで、主に selinux、開発デバイスの作成、uevent メッセージのカーネル レポートの監視、およびファームウェアの読み込みなどの内容です。
FirmwareHandler の処理フロー:
FirmwareHandler の HandleUevent メソッドは、主にファームウェアの読み込みと基礎となるノード間の対話プロセスを処理します。
まず、処理する前に、uevent メッセージのサブシステム タイプがファームウェア フィールドであるかどうかを確認します。このタイプは、カーネルのファームウェア モジュールによってのみ報告されます。
HandleUevent は主に、メイン スレッドを通じてさまざまなサブスレッドを作成し、カーネルからのさまざまなドライバーからのファームウェア要求を並行して処理します。
ProcessFirmwareEvent 関数
最初に、ueventd によってサポートされるパスで取得されたファームウェア ファイルが存在するかどうかをループして判断し、存在する場合は、基礎となる読み込みを書き込みます。属性ファイルを 1 として設定し、同時に取得したファームウェア ファイルをコピーして、基になるデータ ファイルに書き込みます。完了後、基礎となるロード属性ファイルに 0 が書き込まれます。
この時点で、カーネルはユーザー空間によって書き込まれたファームウェア ファイル情報を取得しました。
その中で:
ueventd はデフォルトでファームウェアを検索するためのパスをサポートしています:
ueventd.rc で指定されたfirmware_directory からファイル。
関連する推奨事項: 「Linux ビデオ チュートリアル 」
以上がLinuxファームウェアとは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。